how to write this query in sql - sql

how to write this query in sql :
For every player that has played more than two games, list the player name, total amount of winnings and number of games played for each player". The result should be sorted by the winnings in descending order.
and i have in player table these attributes:
playerId,playerName,age
and in games table these attrubites:
gameId,playerId,results note the results attrubie is filled either by (first or second or third or,..,or no show) the winner is the one who has the result= first
this is my weak query i didn't got the right answer ,but that all what i can do . any idea
select playerName,count(*),count(*)
from games,player
where games.playerId=player.playerId
group by games.results

You want to look into GROUP BY and HAVING in conjunction with COUNT. Something like this would probably do (untested):
SELECT
p.playerName
,COUNT(g.*)
,SUM(g.Winnings) -- you didn't name this column
FROM
games g
INNER JOIN ON g.playerId = p.playerId
WHERE
g.results = 1 -- whatever indicates this player was the winner
GROUP BY
p.playerName
HAVING
COUNT(g.*) > 2

*Try this (pretty much as you said it in English...
(if "winnings" is amount won in the game), then:
Select playerName, count(*) Games, -- Number of game records per player
Sum(g.Winnings) Winnings -- Sum of a Winnings attribute (dollars ??)
from player p Join Games g -- from the two tables
On g.PlayerId = p.PlayerId -- connected using PlayerId
Group by p.playerName -- Output in one row per Player
Having Count(*) > 2 -- only show players w/more than 2 games
Order By Sum(g.Winnings) -- sort the rows based on Player Winnings
if by "Winnings" you mean the number of games won, then...
Select playerName, Count(*) Games, -- Number of game records per player
Sum(Case g.WonTheGame -- or whatever attribute is used
When 'Y' Then 1 -- to specify that player won
Else 0 End) Wins -- Output in one row per Player
From player p Join Games g -- from the two tables
On g.PlayerId = p.PlayerId -- connected using PlayerId
Group by p.playerName -- Output in one row per Player
Having Count(*) > 2 -- only show players w/more than 2 games
Order By Sum(Case g.WonTheGame -- Sort by Number of games Won
When 'Y' Then 1
Else 0 End)

Try this :
SELECT playerName, COUNT(g.PlayerID) as NumberOfPlays
FROM games g ,player p
WHERE g.playerId=p.playerId
GROUP BY g.PlayerID
HAVING COUNT(g.PlayerID) > 1
ORDER BY g.results DESC
SELECT - the data you want to display
FROM - the tables
WHERE - both IDs match each other
GROUP BY - Games PlayerID, so all the counts are correct
HAVING - Make sure they played more then one game
ORDER BY - Order the results the way you want them.

it's tough to glean exactly what you need from your question but try something like this:
select playerName, count(*)
from games g
join player p ON g.playerId = p.playerId
group by playerName
having count(*) > 2
order by games.results DESC

select
playerName,
sum(if(games.result = 'first',1,0)) as wins,
count(*) as gamesPlayed
from player
join games on games.playerId = player.playerId
group by games.results
having count(*) > 2
order by count(*) desc;

Related

The difference between the minimum and maximum number of games

Question: Show the names of all players who have the following:
the difference between the minimum and maximum number of games
this players is greater than 5.
select p.name
from player p
join competition c
on c.playerID = p.playerID
where (
(select count(*) from competition
where count(games) > 1
group by playerID
) - (
select count(*) from competition
where count(games) <= 1
group by playerID
))> 5;
I'm kind of lost. I'm not so sure is this the right way, how I should proceed: should I use count and find the minimum and maximum number of games and compare with greater than 5 or should I use instead of count, min and max functions. Would be very grateful, if someone can explain me the logic of this.
Tables:
player competition
------- --------
playerID playerID
name games
birthday date
address
telefon
SELECT
P.Name,
MIN(C.Games) MinGame,
MAX(C.Games) MaxGame,
FROM Player P
INNER JOIN Competition C
ON C.PlayerId = P.PlayerId
GROUP BY P.Id, P.Name
HAVING MAX(C.Games) - MIN(C.Games) > 5
It should be a simple query:
With tab1 AS (Select player.name, min(games) mx_game, max(games) min_game,
max(games) - min(games) diff
from player JOIN competition ON player.player_id = competition.id
group by player.player_id, player.name)
Select tab1.name from tab1
WHERE diff >5;
I am adding player_id in the group by as player_name could be similar for 2 person.

How to count the difference between two values in SQL?

Sorry if my title is not detailed
I have two tables
Game table:
homeTeam int
awayTeam int
homePoints int
awayPoints int
Team
tid int
name varchar(20)
I am trying to find the number of games won at home by a specific team, lets say 'cops', with Team.tid = Game.homeTeam and wins are counted if homePoints > awayPoints
I want to end up with
Team HomeWins
-----------------
Cops 20
How do I go about that?
EDIT: #
I Managed to get my answer using
SELECT t.name, count(CASE WHEN homePoints > awayPoints then 1 ELSE NULL END) as "Home Wins"
from Team t
JOIN Game g
ON t.tid = g.homeTeam
where t.name = 'Patriots'
GROUP BY t.name
some of the other answers were giving me the following errors
Column 'team.name' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
You should join the tables to be able to get both name and homePoints and use COUNT by homePoints and group by using team id to see a result for each team.
SELECT
T.name, COUNT(G.homePoints)
FROM
team T
INNER JOIN
game G ON G.homeTeam = T.tid
WHERE
G.homePoints > G.awayPoints
GROUP BY T.tid, T.name;
OR if you need the result for a specific team by providing it's id, you may drop the GROUP BY and add condition in the WHERE, e.g.
SELECT
T.name, COUNT(T.tid)
FROM
team T
INNER JOIN
game G ON G.homeTeam = T.tid
WHERE
G.homePoints > G.awayPoints and T.tid = :request_team_id;
First SELECT the columns that we want to display and use AS to specify they headings.
SELECT
team.name as 'Team',
COUNT(game.homePoints) AS 'HomeWins'
FROM dbo.team
Then we use INNER JOIN to only include the entries in game table, which match the Team ID in the homeTeam column vs what we selected from the team table.
INNER JOIN game on team.tid = game.homeTeam
Then we add a WHERE clause to limit it to only the team we ask for team.name = 'cops' and only include wins by that team
WHERE
team.name = 'cops'
AND game.homePoints > game.awayPoints
So all together your script should look like this;
SELECT
team.name as 'Team',
COUNT(game.homePoints) AS 'HomeWins'
FROM dbo.team
INNER JOIN game on team.tid = game.homeTeam
WHERE
team.name = 'cops'
AND game.homePoints > game.awayPoints
GROUP BY team.name

Selecting relation with exact keys in a many to many

I have an M2M relation on two tables in an SQL database, as follows:
Players
-------
Name
ID
Teams
------
Name
ID
PlayersTeams
------
PlayerID
TeamID
A team consists of 1 or more players.
I would like to query for a team given its player IDs, and return only the team that contains exactly those players, no more, no less. So querying for a team with players (1,2,3) would only return team with players 1,2,3, and not a team with players 1,2,3,4.
Is this possible in a single query?
I've got an sqlfiddle I'm trying to work it out in here: http://sqlfiddle.com/#!2/27799/8
in that example i'd like to be able to select the team "john and mick" by querying with player IDs 1 and 2...
update
in this sqlfiddle http://sqlfiddle.com/#!2/27799/69 I can select the team ID 2 ("john and mick") but it also gets team ID 4 ("john, mick and trev"). Need to filter it down to JUST 2.
select TeamId
from PlayersTeams
group by TeamId
having count(*) = sum(case when playerid in (1,2) then 1 else 0 end)
and count(*) = 2
Not familiar with mysql so I don;t know how to get the players list length (the count(*) =2) to make is fully dynamic but you get the point.
I added player 3 in team 3 to create all possible cases. This is my answer:
SELECT t.*
FROM playersteams a,
teams t
WHERE a.teamid = t.id
AND (SELECT COUNT(*) FROM playersteams c
WHERE c.teamid = a.teamid
AND c.playerid = 2) = 1
AND (SELECT COUNT(*) FROM playersteams c
WHERE c.teamid = a.teamid
AND c.playerid = 3) = 1
GROUP BY t.id, t.name
HAVING COUNT(a.playerid) = (SELECT COUNT(*) FROM players WHERE id IN (2,3));
SQL Fiddle: demo

select data that belongs to category

I have three tables like this:
table player:
id, name
table matchevent:
id, player_id, eventcategory_id, description
table eventcategory:
id, name
Relations are:
player : matchevent - 1:N
matchevent : eventcategory - N:1
In table player I have football player names and in eventcategory events, like yellow card, substitution etc. In table matchevent I store player events which belongs to some category.
And now I want to retrieve COUNT of events that all players have. For example:
first player has COUNT of yellow cards 0, substitution 0 and goals 0
second player has 1 yellow card, 0 substitution and 2 goals
third player have 0 yellow cards, 0 substitution 0 goals
etc
How can I do that in DQL? I tried LEFT JOIN and IN, but it doesn't work. It selects only players with events, not all players.
->createQuery('SELECT p, i
FROM MyBundle:player p
LEFT JOIN p.matchevent i
WHERE i.eventcategory IN (:eventcategory)
ORDER BY p.player ASC
')
->setParameters(array(
'eventcategory' => $eventcategory,
))
Use a right join that should force it to return all players even if they don't have events.
'SELECT p, i
FROM MyBundle:player p
RIGHT JOIN p.matchevent i
WHERE i.eventcategory IN (:eventcategory)
ORDER BY p.player ASC
')

SQL, Struggling to believe HAVING can be more efficient than a join

I Am trying to find Players that have played in more than one game for a team in the following tables (** denotes private key), and find it hard to believe the best query I can come up with (below) is the most efficient. Ideas on how to improve it, and explanations as to why would be much appreciated (Trying to learn SQL)
Team (*tid*, name)
Game (*gid*, tid)
Player (*gid*, *name*)
SELECT Team_Name, Player_Name
FROM (SELECT GID, TID FROM GAME) G
,(SELECT NAME AS Player_Name, GID FROM PLAYER) P
,(SELECT NAME AS Team_Name, TID FROM TEAM) T
WHERE ( G.GID = P.GID
AND Player_Name IN (SELECT P.NAME
FROM GAME G
,PLAYER P
WHERE G.GID = P.GID
GROUP BY P.NAME
HAVING COUNT(P.NAME) > 1)
AND T.TID = G.TID
)
GROUP BY Team_Name, Player_Name
HAVING COUNT(Player_Name) > 1
ORDER BY Team_Name
You're asking which players have played in more than a single game.
SELECT P.Player_Name
FROM Player P
GROUP BY P.Player_Name
HAVING COUNT(DISTINCT P.GID) > 1
That will return all players who have played in more than 1 game (GID).
If you'd like to also GROUP BY team, then do this:
SELECT P.Player_Name, T.Team_Name
FROM Player P
JOIN Game G ON P.GID = G.GID
JOIN Team T ON G.TID = T.TID
GROUP BY P.Player_Name, T.Team_Name
HAVING COUNT(DISTINCT G.GID) > 1
It seems odd to have the GID in the Player table. Perhaps having a PlayerGames table would make more sense that stored the PlayerId and GameId -- better for database normalization. The Player table should only store a single record for each player.
Also, what is the real association between the player and the team. In this scenario, you're saying a player has to play a game, and a game has to have a team (or should a game have 2 or more teams). Let us know what you're going for, and we could help present your best option.
Good luck.