create table coaches (
        coachID integer primary key autoincrement,
        coach_name text
);

create table players (
        playerID  integer primary key autoincrement,
        playerName text not null,
        salary integer,
        fk_coach integer,
        constraint abc foreign key (fk_coach) references coaches (coachID)
);

create table matches (
        matchID  integer primary key autoincrement,
        playedAgainst text not null,
        totalScore integer not null,
        bets real not null
);

create table players_matches (
        pmID  integer primary key autoincrement,
        fk_match integer,
        fk_player integer,
        constraint mno foreign key (fk_player) references players (playerID),
        constraint xyz foreign key (fk_match) references matches (matchID)
);

-- three coach_names CHECKED
insert into coaches (coach_name) values ("coach-1"), ("coach-2"), ("coach-3");

-- four players assigned to each coach CHECKED
insert into players (playerName, salary, fk_coach) values
        ("ella", 71, 1), ("alexander", 12, 1), ("eliza", 3, 1),
        ("theo", 91, 1), ("amelia", 82, 2), ("sebastian", 23, 2),
        ("louis", 53, 2), ("henry", 85, 2), ("penlope", 75, 3),
        ("james", 36, 3), ("nora", 46, 3), ("julian", 38, 3);

-- 3, 2, 3 matches in those coach_names
insert into matches (playedAgainst, totalScore, bets) values
        ("Utrecht University", 0, 129),
        ("Wesleyan University", 2, 112),
        ("City University of New York", 4, 118),
        ("Imperial College London", 1, 122),
        ("University of Göttingen", 2, 104),
        ("University of California–Davis", 1, 167),
        ("Dartmouth College", 3, 156),
        ("University of Sydney", 3, 146);

-- summary
insert into players_matches (fk_match, fk_player) values
        (1, 1), (1, 3), (2, 2), (2, 3), (3, 4), (3, 3), (4, 6), (4, 7),
        (5, 8), (5, 6), (6, 12), (6, 9), (7, 11), (7, 9), (8, 11), (8, 12);

analyze;

WITH MyMatches (matchID, playedAgainst, totalScore, bets, totalSalary)
     as (SELECT matchID, playedAgainst, totalScore, bets, (select sum(salary)
                                                             from players, 
players_Matches
                                                            where 
players_matches.fk_player == players.playerID
                                                              and 
players_matches.fk_match == matches.matchID)
          FROM matches)
select coach_name,
       matches.matchid as match_number,
       matches.playedagainst as match,
       playerName as player,
       salary,
       totalsalary - bets
  from players, mymatches as matches, players_matches, coaches
 where players.playerID == players_matches.fk_player
   and matches.matchID == players_matches.fk_match
   and players.fk_coach == coaches.coachID
;

QUERY PLAN
|--SCAN TABLE players_matches (~16 rows)
|--SEARCH TABLE players USING INTEGER PRIMARY KEY (rowid=?) (~1 row)
|--SEARCH TABLE matches USING INTEGER PRIMARY KEY (rowid=?) (~1 row)
|--SEARCH TABLE coaches USING INTEGER PRIMARY KEY (rowid=?) (~1 row)
`--CORRELATED SCALAR SUBQUERY 1
   |--SCAN TABLE players_Matches (~4 rows)
   `--SEARCH TABLE players USING INTEGER PRIMARY KEY (rowid=?) (~1 row)
coach_name  match_number  match               player      salary      
totalsalary - bets
----------  ------------  ------------------  ----------  ----------  
------------------
coach-1     1             Utrecht University  ella        71          -55.0
coach-1     1             Utrecht University  eliza       3           -55.0
coach-1     2             Wesleyan Universit  alexander   12          -97.0
coach-1     2             Wesleyan Universit  eliza       3           -97.0
coach-1     3             City University of  theo        91          -24.0
coach-1     3             City University of  eliza       3           -24.0
coach-2     4             Imperial College L  sebastian   23          -46.0
coach-2     4             Imperial College L  louis       53          -46.0
coach-2     5             University of Gött  henry       85          4.0
coach-2     5             University of Gött  sebastian   23          4.0
coach-3     6             University of Cali  julian      38          -54.0
coach-3     6             University of Cali  penlope     75          -54.0
coach-3     7             Dartmouth College   nora        46          -35.0
coach-3     7             Dartmouth College   penlope     75          -35.0
coach-3     8             University of Sydn  nora        46          -62.0
coach-3     8             University of Sydn  julian      38          -62.0

Creating the missing indexes:

sqlite> .lint fkey-indexes
CREATE INDEX 'players_fk_coach' ON 'players'('fk_coach'); --> coaches(coachID)
CREATE INDEX 'players_matches_fk_match' ON 'players_matches'('fk_match'); --> 
matches(matchID)
CREATE INDEX 'players_matches_fk_player' ON 'players_matches'('fk_player'); --> 
players(playerID)
sqlite>
sqlite> CREATE INDEX 'players_fk_coach' ON 'players'('fk_coach'); --> 
coaches(coachID)
sqlite> CREATE INDEX 'players_matches_fk_match' ON 
'players_matches'('fk_match'); --> matches(matchID)
sqlite> CREATE INDEX 'players_matches_fk_player' ON 
'players_matches'('fk_player'); --> players(playerID)
sqlite> analyze;

sqlite> WITH MyMatches (matchID, playedAgainst, totalScore, bets, totalSalary)
   ...>      as (SELECT matchID, playedAgainst, totalScore, bets, (select 
sum(salary)
   ...>                                                              from 
players, players_Matches
   ...>                                                             where 
players_matches.fk_player == players.playerID
   ...>                                                               and 
players_matches.fk_match == matches.matchID)
   ...>           FROM matches)
   ...> select coach_name,
   ...>        matches.matchid as match_number,
   ...>        matches.playedagainst as match,
   ...>        playerName as player,
   ...>        salary,
   ...>        totalsalary - bets
   ...>   from players, mymatches as matches, players_matches, coaches
   ...>  where players.playerID == players_matches.fk_player
   ...>    and matches.matchID == players_matches.fk_match
   ...>    and players.fk_coach == coaches.coachID
   ...> ;
QUERY PLAN
|--SCAN TABLE players_matches (~16 rows)
|--SEARCH TABLE players USING INTEGER PRIMARY KEY (rowid=?) (~1 row)
|--SEARCH TABLE matches USING INTEGER PRIMARY KEY (rowid=?) (~1 row)
|--SEARCH TABLE coaches USING INTEGER PRIMARY KEY (rowid=?) (~1 row)
`--CORRELATED SCALAR SUBQUERY 1
   |--SEARCH TABLE players_Matches USING INDEX players_matches_fk_match 
(fk_match=?) (~2 rows)
   `--SEARCH TABLE players USING INTEGER PRIMARY KEY (rowid=?) (~1 row)
coach_name  match_number  match               player      salary      
totalsalary - bets
----------  ------------  ------------------  ----------  ----------  
------------------
coach-1     1             Utrecht University  ella        71          -55.0
coach-1     1             Utrecht University  eliza       3           -55.0
coach-1     2             Wesleyan Universit  alexander   12          -97.0
coach-1     2             Wesleyan Universit  eliza       3           -97.0
coach-1     3             City University of  theo        91          -24.0
coach-1     3             City University of  eliza       3           -24.0
coach-2     4             Imperial College L  sebastian   23          -46.0
coach-2     4             Imperial College L  louis       53          -46.0
coach-2     5             University of Gött  henry       85          4.0
coach-2     5             University of Gött  sebastian   23          4.0
coach-3     6             University of Cali  julian      38          -54.0
coach-3     6             University of Cali  penlope     75          -54.0
coach-3     7             Dartmouth College   nora        46          -35.0
coach-3     7             Dartmouth College   penlope     75          -35.0
coach-3     8             University of Sydn  nora        46          -62.0
coach-3     8             University of Sydn  julian      38          -62.0



---
The fact that there's a Highway to Hell but only a Stairway to Heaven says a 
lot about anticipated traffic volume.


>-----Original Message-----
>From: sqlite-users [mailto:sqlite-users-
>boun...@mailinglists.sqlite.org] On Behalf Of Keith Medcalf
>Sent: Monday, 18 February, 2019 09:24
>To: SQLite mailing list
>Subject: Re: [sqlite] How to get aggregate without reducing number of
>rows (repeats are ok)?
>
>
>On Monday, 18 February, 2019 02:27, Rocky Ji <rockyji3...@gmail.com>:
>
>>Awesome, thanks for the detailed analysis; this is why I love
>mailing
>>lists.
>
>>It seems you jumped to the meat directly, in the opening of my
>>question,
>>notice the words "scenario" and "given".
>>I am sure you know what they mean, but for record: the links I gave
>>help in
>>"reproducing the problem" in a minimal viable way.
>>Don't worry too much about ROWID, there are no deletes/updates on
>our
>>little example.
>>Finally, please reread the OP, I explicitly mentioned the
>>conditions/relations exactly as they are supposed to be; if the
>words
>>team
>>/ player / coach make you uncomfortable, use abcd...
>
>>Now, can we get the desired result without nested `select`s?
>
>Why?  Would you like the prose to not use the words "the" and "then"
>as well?
>
>---
>The fact that there's a Highway to Hell but only a Stairway to Heaven
>says a lot about anticipated traffic volume.
>
>>On Mon, Feb 18, 2019, 10:56 AM Keith Medcalf <kmedc...@dessus.com
>>wrote:
>>
>>>
>>>
>>> create table coaches (coach_name text);
>>>
>>> create table players (
>>>         playerName text not null,
>>>         salary integer,
>>>         fk_coach text,
>>>         constraint abc foreign key (fk_coach) references coaches
>>> (coach_name)
>>> );
>>>
>>> create table matches (
>>>         playedAgainst text not null,
>>>         totalScore integer not null,
>>>         bets real not null
>>> );
>>>
>>> create table players_matches (
>>>         fk_match integer,
>>>         fk_player integer,
>>>         constraint mno foreign key (fk_player) references players
>>(ROWID),
>>>         constraint xyz foreign key (fk_match) references matches
>>(ROWID)
>>> );
>>>
>>> 1)  You do not have any columns in either PLAYERS or MATCHES
>called
>>> ROWID.  Foreign Keys may only refer to explicitly named columns.
>>> 2)  The tables have no PRIMARY KEY.  Therefore there is no way to
>>identify
>>> a particular set of attributes in a table (tuple).
>>> 3)  text fields for playerName and Coach_Name are ill defined
>(case
>>> sensitive/insensitive?  Unique?)
>>> 4)  Parent Keys should be UNIQUE, Child Keys may be unique (1:1)
>or
>>not
>>> unique (1:N) (but nevertheless must be indexed)
>>>
>>> Your data structure does not model reality.  Players are on Teams.
>>> Coaches coach Teams.  I suppose you could short-circuit and
>>eliminate Teams
>>> by assigning Players to Coaches, but that means the same coach may
>>never
>>> coach different teams.  Matches are between Teams (or coaches
>>players if
>>> you have gotten rid of teams).
>>>
>>> Or is this to model school-children at recess, where the so-called
>>team is
>>> merely the happenstance of the "John Picks Chris" and "Alice Picks
>>Don"
>>> verses the next recess where "John Picks Don" and "Alice gets
>stuck
>>with
>>> Chris"?
>>>
>>> In any event, why do you not use table generating subqueries that
>>return
>>> the data that you want to play with?  In other words, once you
>know
>>what
>>> data you need then you generate that data.
>>>
>>> For example.  You say " for a match X, profit/match is `sum(salary
>>of all
>>> players playing in X) - X.bets"
>>>
>>> So let us compute that using your wierd and invalid schema:
>>>
>>> select matches.rowid as match, (select sum(salary)
>>>                                   from players, players_matches
>>>                                  where players.rowid ==
>>> players_matches.fk_player
>>>                                    and players_matches.fk_match ==
>>> matches.rowid) - matches.bets AS profitmatch
>>>   from matches
>>> ;
>>>
>>>
>>>
>>>
>>> So now you have the "profitmatch" for each match.
>>>
>>> The you also want a bunch of detail crap using the same wierd and
>>invalid
>>> schema:
>>>
>>> select fk_coach as coach_name,
>>>        matches.rowid as match_number,
>>>        matches.playedagainst as match,
>>>        playerName as player,
>>>        salary
>>>   from players, matches, players_matches
>>>  where players.rowid == players_matches.fk_player
>>>    and matches.rowid == players_matches.fk_match
>>> ;
>>>
>>> And then you want to join those together based on the match:
>>>
>>> select fk_coach as coach_name,
>>>        matches.rowid as match_number,
>>>        matches.playedagainst as match,
>>>        playerName as player,
>>>        salary,
>>>        profitmatch as profit
>>>   from players, matches, players_matches,
>>>        (
>>>         select matches.rowid as match, (select sum(salary)
>>>                                           from players,
>>players_matches
>>>                                          where players.rowid ==
>>> players_matches.fk_player
>>>                                            and
>>players_matches.fk_match ==
>>> matches.rowid) - matches.bets AS profitmatch
>>>           from matches
>>>        ) as profit
>>>  where players.rowid == players_matches.fk_player
>>>    and matches.rowid == players_matches.fk_match
>>>    and profit.match == matches.rowid
>>> ;
>>>
>>> The SQL is correct and produces the results, however, since the
>>schema is
>>> invalid it is difficult to actually run it.  Simplifications are
>>possible
>>> (there is no point in including the "matches" table twice, for
>>example, and
>>> the correlated subquery could be put right in the main query, and
>>if the
>>> database schema itself were normalized, then even further
>>simplifications
>>> would be possible).
>>>
>>> ---
>>> The fact that there's a Highway to Hell but only a Stairway to
>>Heaven says
>>> a lot about anticipated traffic volume.
>>>
>>> >-----Original Message-----
>>> >From: sqlite-users [mailto:sqlite-users-
>>> >boun...@mailinglists.sqlite.org] On Behalf Of Rocky Ji
>>> >Sent: Sunday, 17 February, 2019 20:19
>>> >To: SQLite mailing list
>>> >Subject: Re: [sqlite] How to get aggregate without reducing
>number
>>of
>>> >rows (repeats are ok)?
>>> >
>>> >@Keith
>>> >
>>> >Thanks. I am new to SQL and DB in general; please clarify what
>*is
>>it
>>> >valid* means. How do I check validity of schema?
>>> >
>>> >On Mon, Feb 18, 2019, 1:17 AM Keith Medcalf <kmedc...@dessus.com
>>> >wrote:
>>> >
>>> >>
>>> >> Nice schema.  Do you have a valid one?
>>> >>
>>> >>
>>> >> ---
>>> >> The fact that there's a Highway to Hell but only a Stairway to
>>> >Heaven says
>>> >> a lot about anticipated traffic volume.
>>> >>
>>> >>
>>> >> >-----Original Message-----
>>> >> >From: sqlite-users [mailto:sqlite-users-
>>> >> >boun...@mailinglists.sqlite.org] On Behalf Of Rocky Ji
>>> >> >Sent: Sunday, 17 February, 2019 09:47
>>> >> >To: SQLite mailing list
>>> >> >Subject: [sqlite] How to get aggregate without reducing number
>>of
>>> >> >rows (repeats are ok)?
>>> >> >
>>> >> >Hello everyone,
>>> >> >
>>> >> >How can I prevent group by clause from reducing the number of
>>rows
>>> >> >without
>>> >> >affecting accuracy of what aggregate functions provide?
>>> >> >
>>> >> >Scenario:
>>> >> >My club has-many coaches.
>>> >> >Each coach trains a team of players.
>>> >> >Of course, a player has-many matches and a match has-many
>>players.
>>> >> >Given the schema: https://pastebin.com/raw/C77mXsHJ
>>> >> >and sample data: https://pastebin.com/raw/GhsYktRS
>>> >> >
>>> >> >I want a result like: https://pastebin.com/raw/stikDvYS
>>> >> >
>>> >> >NOTE: for a match X, profit/match is `sum(salary of all
>players
>>> >> >playing in
>>> >> >X) - X.bets`
>>> >> >
>>> >> >To get the result, here's what I came up with:
>>> >> >https://pastebin.com/ckgicBWS
>>> >> >
>>> >> >If I un-comment those lines, I get the profit column but rows
>>are
>>> >> >reduced,
>>> >> >how can I prevent that?
>>> >> >
>>> >> >Thanks,
>>> >> >Rocky.
>>> >> >_______________________________________________
>>> >> >sqlite-users mailing list
>>> >> >sqlite-users@mailinglists.sqlite.org
>>> >> >http://mailinglists.sqlite.org/cgi-
>bin/mailman/listinfo/sqlite-
>>> >users
>>> >>
>>> >>
>>> >>
>>> >> _______________________________________________
>>> >> sqlite-users mailing list
>>> >> sqlite-users@mailinglists.sqlite.org
>>> >> http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-
>>> >users
>>> >>
>>> >_______________________________________________
>>> >sqlite-users mailing list
>>> >sqlite-users@mailinglists.sqlite.org
>>> >http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-
>>users
>>>
>>>
>>>
>>> _______________________________________________
>>> sqlite-users mailing list
>>> sqlite-users@mailinglists.sqlite.org
>>> http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-
>>users
>>>
>>_______________________________________________
>>sqlite-users mailing list
>>sqlite-users@mailinglists.sqlite.org
>>http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users
>
>
>
>_______________________________________________
>sqlite-users mailing list
>sqlite-users@mailinglists.sqlite.org
>http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users



_______________________________________________
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to