SQLQuery COUNT number of games per team - sql

I have 4 tables:
Teams
codTeam: 1
year: 1995
codYears: 1
codType: 1
name: FCP
points: 3
codTeam: 2
year: 1990
codYears: 1
codType: 1
name: SLB
points: 3
codTeam: 3
year: 1995
codYears: 3
codType: 2
name: BCP
points: 0
Trainers (People who train a team)
codTrainer: 1
name: Peter
street: Ghost street
cellphone: 252666337
birthdayDate: 1995-02-01
BI: 11111111
number: 121212121
codTrainer: 1
name: Pan
street: Ghost street Remade
cellphone: 253999666
birthdayDate: 1995-01-01
BI: 22222222
number: 212121212
TeamsTrainers (In which team is someone training)
codTeamTrainer: 1
codTeam: 1
codTrainer: 2
dataInicio: 1998-05-05
codTeamTrainer: 2
codTeam: 2
codTrainer: 2
dataInicio: 1998-06-07
codTeamTrainer: 3
codTeam: 2
codTrainer: 1
dataInicio: 1999-09-09
Games
codGame: 1
date: 2015-02-12 13:00:00
codTeamHome: 1
codTeamAgainst: 2
goalsHome: 3
goalsAgainst: 2
codTypeGame: 1
codGame: 2
date: 2015-02-12 15:00:00
codTeamHome: 2
codTeamAgainst: 1
goalsHome: 1
goalsAgainst: 2
codTypeGame: 3
So basically I want to:
Get the table Games and show:
Team Name | Trainer Name | Goals Home | Goals Against | Points | Ammout of Games from the Home Team
I have the following code for that in SQLQuery:
SELECT Teams.name, Trainers.name, Games.goalsHome,
Games.goalsAgainst, Teams.points, COUNT(*)
FROM Teams, Trainers, Games, TeamsTrainers
WHERE Games.codTeamHome = Teams.codTeam AND
TeamsTrainers.codTeam = Teams.codTeam AND
TeamsTrainers.codTrainer = Trainers.codTrainer
GROUP BY Teams.name, Trainers.name, Games.goalsHome,
Games.goalsAgainst, Teams.points
(May have some errors as I translated)
Yet, the COUNT only shows 1 (Probably because on the WHERE it has "teamHome" so it only counts 1), yet, if it's because of that, how do I fix it?
Result:
FCP | Pan | 3 | 2 | 3 | 1 (Count)
SLB | Peter | 1 | 2 | 3 | 1 (Count)
SLB | Pan | 1 | 2 | 3 | 1 (Count)
It should be 2 for each one on the Count
Any idea?

The reason you get wrong result is of wrong joing data type. You should use repsectivelly: left, right or inner join instead of joing data via using where clause. Your data model provides 1 to N relationship, so you should use specific type of join.
See: http://www.codeproject.com/Articles/33052/Visual-Representation-of-SQL-Joins
EDIT
SELECT Te.name, Tr.name, Ga.goalsHome, Ga.goalsAgainst, Te.points,
(SELECT COUNT(*)
FROM Games
WHERE codTeamHome = Te.codTeam OR codTeamAgainst = Te.codTeam)
AS CountOfGames
FROM TeamsTrainers AS Tt
LEFT JOIN Teams AS Te ON Tt.codTeam = Te.codTeam
LEFT JOIN Trainers AS Tr ON Tt.codTrainer = Tr.codTrainer
LEFT JOIN Games AS Ga ON Ga.codTeamHome = Te.codTeam
SQL Fiddle

You can change your WHERE clause by saying
[what you have] OR (Games.codTeamAgainst = Teams.codTeam AND ...)
However, this probably causes other problems because you probably care about whether a particular team scores the goals, not whether the home team scores the goals in games that team plays on either side.
You might not notice the other problems for a while because your GROUP BY clause is probably pretty far from what you want, and you might want to be selecting aggregate functions for a much simpler grouping.

Related

How do I match two ids against the same value (SQL)

I have a SQL question.
Say I have three tables:
Table 1: Artist
id bandid name
1 1 Paul McCartney
2 1 Ringo Starr
3 1 John Lennon
4 1 George Harrison
5 2 Mick Jagger
6 2 Keith Richards
7 2 Charlie Watts
8 2 Ronnie Wood
9 3 Travis Barker
10 3 Tom Delonge
11 3 Mark Hoppus
Table 2: Band
bandid bandname
1 the beatles
2 rolling stones
3 blink 182
Table 3: Artist on Album
albumid artistid
1 1
1 2
1 3
1 4
2 1
2 2
2 3
2 4
3 5
3 6
3 7
I'm seeking to count the number of albums two artists have worked together on, listing artist #1 and artist #2 names, the band they are both in, and the number of albums between them, while using an subquery. Another note: listing artist #1 against artist #2 is not a duplicate to listing artist #2 against artist #1.
A self join is one approach here:
SELECT a1.name, a2.name, COUNT(*) AS num_shared_albums
FROM ArtistOnAlbum al1
INNER JOIN ArtistOnAlbum al2
ON al1.albumid = al2.albumid AND
al1.artistid < al2.artistid
INNER JOIN Artist a1
ON al1.artistid = a1.id
INNER JOIN Artist a2
ON al2.artistid = a2.id
GROUP BY
a1.id, a2.id;
Demo

Use LEFT OUTER JOIN to include NULL values in query

I want the final query to include manufacturer_id | manufacturer_name | ice_cream_id | ice_cream_name so that the print includes also those manufacturer_names, which are included in the database but do not have any ice creams (NULL ice_cream_names). Then I want the results in ascending order by manufacturer.manufacturer_id, ice_cream.ice_cream_id which i already managed to do.
Here is my sample code and sample header of the dataset I deal with:
SELECT manufacturer.manufacturer_id, manufacturer.manufacturer_name, ice_cream.ice_cream_id, ice_cream.ice_cream_name
FROM ice_cream LEFT OUTER JOIN manufacturer
ON ice_cream.manufacturer_id = manufacturer.manufacturer_id OR manufacturer.manufacturer_name IS NULL
ORDER BY manufacturer.manufacturer_id, ice_cream.ice_cream_id ASC;
manufacturer
manufacturer_id manufacturer_name country
--------------- ----------------- ----------
1 Jen & Berry Canada
2 4 Friends Finland
3 Gelatron Italy
ice_cream
ice_cream_id ice_cream_name manufacturer_id manufacturing_cost
------------ ---------------- --------------- ------------------
1 Plain Vanilla 1 1
2 Vegan Vanilla 2 0.89
3 Super Strawberry 2 1.44
4 Very plain 2 1.2
ingredient
ingredient_id ingredient_name kcal protein plant_based
------------- --------------- ---------- ---------- -----------
1 Cream 400 3 0
2 Coconut cream 230 2.3 1
3 Sugar 387 0 1
4 Vanilla extract 12 0 1
5 Strawberry 33 0.7 1
6 Dark chocolate 535 8 1
contains
ice_cream_id ingredient_id quantity
------------ ------------- ----------
1 1 70
1 3 27
1 4 3
2 2 74
2 3 21
2 4 5
3 1 60
3 3 10
3 5 30
4 2 95
4 4 5
I wonder what's the logic between FROM table1 LEFT OUTER JOIN table 2; Are those in right order? And I think I do something extra in the "ON" stage that should be done in WHERE?
You want to keep all manufacturers according to your description. Hence, that table should be the first table in the LEFT JOIN. I would also suggest using table aliases:
SELECT m.manufacturer_id, m.manufacturer_name, i.ice_cream_id, i.ice_cream_name
FROM manufacturer m LEFT JOIN
ice_cream ic
ON ic.manufacturer_id = m.manufacturer_id
ORDER BY m.manufacturer_id, ic.ice_cream_id ASC;
This doesn't require any fiddling with the ON clause, just proper use of the LEFT JOIN.

Joining player and game tables to get player points

I have the following SQL tables and I'm basically trying to pull a table of every game that Ralph played in for 2018, and the amount of points scored.
Ralph has a unique_id, but may play on multiple teams, or in different positions. Each year that he plays has a new record entered into the player info table for each of those teams and/or positions.
The games data table's player ID may use both of Ralph's player info records, so for instance, records 1 and 2 of game data are both for Ralph, and his actual total points scored is 18 (12 + 6). I don't need those points to be added together, as that can be done easier in PHP, but I do need both records pulled.
------------------------------
Player Info as pi
------------------------------
id | unique_id | year | name | team | pos
1 5000 2018 Ralph 5 F
2 5000 2018 Ralph 5 C
3 5600 2018 Bill 5 G
4 5000 2017 Ralph 4 F
5 2688 2016 Mike 6 G
------------------------------
Game Info as gi
------------------------------
id | team 1 | team 2
1 5 6
2 6 5
3 8 3
4 6 2
------------------------------
Game Data as gd
------------------------------
id | game_info_id | player_id | Points
1 1 1 12
2 1 2 6
3 2 1 4
4 4 5 6
The table should show pi.id, pi.unique_id, gi.id, gd.* WHERE gd.player_id = Any of Ralph's pi.id's AND pi.year=2018
Any help here is appreciated, this seems a bit out of my wheelhouse.
Join the tables like this:
select
pi.id, pi.unique_id, gi.id, gd.*
from playerinfo pi
inner join gameinfo gi on pi.team in (gi.team1, gi.team2)
inner join gamedata gd on gd.game_info_id = gi.id and gd.player_id = pi.id
where pi.name = 'Ralph' and pi.year = 2018

SQL - conditional statements in crosstab queries - say what

I am working with MS Access 2007. I have 2 tables: Types of Soda, and Likeability.
Types of Soda are: Coke, Pepsi, Dr. Pepper, and Mello Yellow
Likeability is a lookup with these options: Liked, Disliked, No preference
I know how to count the number of Cokes or Mello Yellows in the table using DCount("[Types]", "[Types of Soda]", "[Types]" = 'Coke')
I also know how to count the number of Liked, Disliked, No preference.
("[Perception]", "[Likeability]", "[Perception]" = 'Liked')
But, what if I need to count the number of "Likes" by Type.
i.e. the table should look like this:
Coke | Pepsi | Dr. Pepper | Mello Yellow
Likes 9 2 12 19
Dislikes 2 45 1 0
No Preference 0 12 14 15
I know in Access I can create a cross tab queries, but my tables are joined by an ID. So my [Likeability] table has an ID column, which is the same as the ID column in my [Types] table. That's the relationship, and that's what connects my tables.
My problem is that I don't know how to apply the condition for counting the likes, dislikes, etc, for ONLY the Types that I specify. It seems like I first have to check the [Likeability] table for "Likes", and cross reference the ID with the ID in the [Types] table.
I am very confused, and you may be too, now. But all I want to do is count the # of Likes and Dislikes for each type of soda.
Please help.
Its not really clear (to me anyway) what your tables look like so lets assume the following
tables
Soda
------
Soda_ID (Long Integer (Increment))
Soda_Name (Text(50)
Perception
------
Perception_ID (Long Integer (Increment))
Perception_Name (Text(50)
Likeability
-----------
Likeability_ID (Long Integer (Increment))
Soda_ID (Long Integer)
Perception_ID (Long Integer)
User_ID (Long Integer)
Data
Soda_Id Soda_Name
------- ---------
1 Coke
2 Pepsi
3 Dr. Pepper
4 Mello Yellow
Perception_ID Perception_Name
------------- ---------
1 Likes
2 Dislikes
3 No Preference
Likeability_ID Soda_ID Perception_ID User_ID
-------------- ------- ------------- -------
1 1 1 1
2 2 1 1
3 3 1 1
4 4 1 1
5 1 2 2
6 2 2 2
7 3 2 2
8 4 2 2
9 1 3 3
10 2 3 3
11 3 3 3
12 4 3 3
13 1 1 5
14 2 2 6
15 2 2 7
16 3 3 8
17 3 3 9
18 3 3 10
Transform query You could write a query like this
TRANSFORM
Count(l.Likeability_ID) AS CountOfLikeability_ID
SELECT
p.Perception_Name
FROM
Soda s
INNER JOIN (Perception p
INNER JOIN Likeability l
ON p.Perception_ID = l.Perception_ID)
ON s.Soda_Id = l.Soda_ID
WHERE
p.Perception_Name<>"No Preference"
GROUP BY
p.Perception_Name
PIVOT
s.Soda_Name;
query output
Perception_Name Coke Dr_ Pepper Mello Yellow Pepsi
--------------- ---- ---------- ------------ -----
Dislikes 1 1 1 3
Likes 2 1 1 1

Force a value of 0 for non-existing value

Group, I am going to try and explain this as best I can, and I hope it makes (some) sense. I am pulling data from a view I have created that tells me a "Sponsor's" customer types and how many of those accounts by CustomerType are inactive after 1 year, 2 years and 3 years. For example:
SponsorID | CustomerType | ExpiredAfter | Total
1234 D 1 Year 5
1234 RA 1 Year 7
1234 CA 1 Year 3
1234 D 2 Years 2
1234 RA 2 Years 4
1234 CA 2 Years 1
1234 D 3 Years 8
1234 RA 3 Years 1
1234 CA 3 Years 6
The problem I am having is a SponsorID might not have any RA that ExpiredAfter 1 year, so nothing shows up in the data. So instead of getting:
SponsorID | CustomerType | ExpiredAfter | Total
1235 D 1 Year 5
1235 RA 1 Year 0
1235 CA 1 Year 3
I get:
SponsorID | CustomerType | ExpiredAfter | Total
1235 D 1 Year 5
1235 CA 1 Year 3
Again, not sure if any of this makes any sense, but what I want to do is include all customer types for all ExpiredAfter regardless if there are values or not. If there isn't a value I just want to force a 0 or Null. I need that data row with 0 for reporting purposes.
Any suggestions?
It sounds like you need to use a LEFT JOIN instead of an INNER JOIN.
You may also have to use ISNULL(total, 0) or COALESCE(total, 0) depending on which DBMS you are using, and your query (as stated by womp)... because if TOTAL is calculated, then having a null value from a LEFT JOIN would still leave you without a 0 value.
Seems to me like you are seeking positive reporting. Try using a cross join. Cross joins link all rows from one table to all rows in the other table thereby giving all possible results as output