How to group by Max? - sql

I'm having some trouble with a statement,
I have a table like this
Player Number
Sport
Date
1
soccer
4/1
4
basketball
4/2
2
basketball
4/3
3
soccer
4/1
1
baseball
4/2
4
basketball
4/3
5
soccer
4/1
3
baseball
4/2
5
soccer
4/2
2
basketball
4/3
1
soccer
4/4
2
baseball
4/5
3
soccer
4/4
4
soccer
4/5
5
soccer
4/3
5
basketball
4/5
I'm trying to write a query that will give me a table that will group together the players by their most played sport so the end result will look like this:
Sport
# of Players Who played the sport the most
Baseball
2
Basketball
1
Soccer
2
I was able to write a statement that shows the number of times each player played a a specific sport but am having trouble getting the table to only select the rows with the highest number of plays and arranging it to be grouped by each sport.
Select distinct PLAYER_NUMBER, SPORT, Max(GAMES_PLAYED) as GAMES_PLAYED
FROM #temp
Group By SPORT, PLAYER_NUMER
order by GAMES_PLAYED desc

I don't think your desired results match your sample data?
Anyway start with a query to get the number of plays per player, and use the row_number window function to determine which sport was played the most for each player (note what do you want to do in the case of a tie?). Then in the next query only use the sport with the most plays per player and group by sport.
with cte as (
select *
-- For each player get the sport with the most plays
, row_number() over (partition by Player order by count(*) desc) rn
from #temp
group by Player, Sport
)
select Sport
, count(*) [# of Players Who played the sport the most]
from cte
where rn = 1
group by Sport
order by Sport;
Returns:
Sport
# of Players Who played the sport the most
basketball
2
soccer
3
The following related query allows one to confirm the results shown above:
with cte as (
select *
, count(*) num
, row_number() over (partition by Player order by count(*) desc) rn
from #temp
group by Player, Sport
)
select Player, Sport, num
from cte
order by Player, num desc;
Which shows for each player which sport was played the most i.e. its the first row for each player, and note baseball never shows up as the most played sport! The actual results are calculated using every rn=1 because that is the sport most played per player.
Player
Sport
num
rn
1
soccer
2
1
1
baseball
1
2
2
basketball
2
1
2
baseball
1
2
3
soccer
2
1
3
baseball
1
2
4
basketball
2
1
4
soccer
1
2
5
soccer
3
1
5
basketball
1
2

If I understand you right, you might also get this by subqueries
select s.sport,
count(distinct s.playdate) as times_played,
(select max(t.players) from (
select count(distinct s2.player) as players
from sports s2
where s2.sport = s.sport
group by s2.sport, s2.playdate
) t
) as nbr_players
from sports s
group by s.sport
this gets me
sport
times_played
nbr_players
baseball
2
2
basketball
3
2
soccer
5
3
DBFiddle here

Related

Custom row cell in SQL

So I'm looking to use a custom row cell to label my data.
Basketball
Baseball
Golf
Cost
1
0
0
$50
0
1
0
$75
1
0
1
$150
0
1
1
$225
The table I have is above. What I'm trying to do is below:
OUTPUT:
Sport
Cost
Basketball
200
Baseball
300
Golf
375
I can get the sum of each sport but I'm having trouble making an alias for each sport on the output table (The first column)
How would I go about that? I've done an alias for a column header, but never for a row cell.
Thanks in advance!
select game
,sum(cost*flg) as cost
from t
cross join lateral (
values
(basketball, 'basketball')
,(baseball, 'baseball')
,(golf, 'golf')
) t2(flg, game)
group by game
game
cost
golf
375
baseball
300
basketball
200
Fiddle
Use a UNION with different WHERE conditions:
select sport, sum(cost)
from
(
select 'Basketball' as sport, cost
from the_table
where basketball = 1
union all
select 'Baseball', cost
from the_table
where baseball = 1
union all
select 'Golf', cost
from the_table
where golf = 1
) t
group by sport;

Remove records based on priority in sql server

details table
name age sports
john 27 football
john 27 cricket
john 27 basketball
kyle 28 baseball
kyle 28 football
nick 24 football
nick 24 hockey
ron 35 football
Priority table :
name priority
futsal 1
basketball 2
football 3
cricket 4
baseball 5
hockey 6
desired table :
name age sports
john 27 basketball --as basketball has the highest priority for john
kyle 28 baseball
nick 24 football
ron 35 football
What is desired is that i want to keep only 1 record for a name and rest should be deleted based on priority of sports .
I know to delete duplicate records but can anyone suggest me can this be accomplished in sql server and
how!!
Do the join use row_number():
select t.*
from (select d.name, d.age, d.sports,
row_number() over (partition by d.name order by p.priority) as seq
from details d inner join
priority p
on p.name = d.sports
) t
where seq = 1;
You can use window functions. Here is one method:
select dp.*
from (select d.*, min(p.priority) over (partition by d.name)
from details d join
priorities p
on d.sport = p.name
) dp
where seqnum = 1;

Equivalent of excel COUNTIFS

I am trying to get a COUNTIFS from excel type of result
Here is the products table:
Name Product
john car
john football
john image
max food
max tv
max laptop
max image
max image
max image
alex tv
alex laptop
alex image
alex cake
alex cake
alex cake
alex cake
alex car
The output should be:
Name Product Number of products per person Number of products of the same type
john car 1 2
john football1 1
john image 1 5
max food 1 1
max tv 1 2
max laptop 1 2
max image 3 5
alex tv 1 2
alex laptop 1 2
alex image 1 5
alex cake 4 4
alex car 1 2
Number of products per person is count of products by name by product
and Number of products of the same type is based on the total count by product
for example image is repeated 3 times for max so in col C the answer is 3 but it there 5 times in the table so answer in col D is 5
I tried but not getting the correct answer:
SELECT
name,
product,
COUNT(*),
COUNT(*) OVER (PARTITION BY product),
from products
GROUP BY 1,2
ORDER BY 1
You are quite close. You need to sum the COUNT(*). You can do this directly in the aggregation query:
SELECT name, product,
COUNT(*),
SUM(COUNT(*)) OVER (PARTITION BY product)
FROM products
GROUP BY 1, 2
ORDER BY 1
#standardSQL
SELECT name, product, product_per_person,
SUM(product_per_person) OVER(PARTITION BY product) product_total
FROM (
SELECT
name,
product,
COUNT(*) product_per_person
FROM `project.dataset.products`
GROUP BY 1,2
)
ORDER BY 1
if to apply to your sample data - result should be
Row name product product_per_person product_total
1 alex cake 4 4
2 alex car 1 2
3 alex image 1 5
4 alex laptop 1 2
5 alex tv 1 2
6 john car 1 2
7 john football 1 1
8 john image 1 5
9 max food 1 1
10 max image 3 5
11 max laptop 1 2
12 max tv 1 2
use group by name and product
SELECT name,
product,
COUNT(*),
COUNT(*) OVER (partition by product)
from products
GROUP BY name,product
ORDER BY 1

SQL statement to select an object that has multiple attributes in the same column

If I were given the following table ATHELTE
PLAYER_NAME SPORT_PLAYED YEAR_PLAYED
---------- ----------- ------------
BOB Basketball 2010
BOB Basketball 2011
BOB Basketball 2012
JOHN Basketball 2010
JOHN Soccer 2011
...
and I want to find a player who has played the same sports across multiple years (in this case it should return BOB since he played basketball for three years) what is the statement to reach the name?
Below is my attempt
SELECT DISTINCT PLAYER_NAME
FROM ATHLETE
HAVING count(YEAR_PLAYED > 1)
But for some reason it returns an empty set
select player_name, sport_played, count(*)
from athlete group by player_name, sport_played having count(*) > 1

How do I get the sum of values from multiple columns in SQL

I have the following table:
Season Name1 Goal1 Name2 Goal2 Name3 Goal3
1990 Smith 2 Abel 1 John 3
1990 Smith 1 Abel 1 John 1
1990 John 0 Smith 2 Abel 5
1991 John 1 Smith 1 Abel 2
1991 Abel 2 John 0 Smith 0
1992 Abel 3 John 0 Smith 1
Season indicates a soccer season, name1, name2 indicates a players position in a given game
Goal1 indicates the number of goals Name1 scored
I would like to generate a list for each name per season how many times they played and the # of goals they scored. Something like this:
Abel 1990 3 games played 7 goals scored
Abel 1991 2 games played 4 goals scored
Abel 1992 1 games played 3 goals scored
John 1990 3 games played 2 goals scored
Any help would be appreciated!
SELECT
sub.player,
sub.Season,
Count(*) AS games_played,
Sum(sub.goals) AS SumOfgoals
FROM
(
SELECT Season, Name1 AS player, Goal1 AS goals
FROM YourTable
UNION ALL
SELECT Season, Name2, Goal2
FROM YourTable
UNION ALL
SELECT Season, Name3, Goal3
FROM YourTable
) AS sub
GROUP BY sub.player, sub.Season
ORDER BY sub.player, sub.Season;
Notice you must use UNION ALL in that subquery. If you use just UNION instead, the subquery result set would include only one row for each combination of Season, player and goals. But when a player scores the same number of goals in more than one game during a season, you want to preserve each of those rows in order to allow an accurate count of games played and total goals scored.
Using your sample data in Access 2007, that query produces this result set.
player Season games_played SumOfgoals
Abel 1990 3 7
Abel 1991 2 4
Abel 1992 1 3
John 1990 3 4
John 1991 2 1
John 1992 1 0
Smith 1990 3 5
Smith 1991 2 1
Smith 1992 1 1
Ok, well, since you aren't sharing what RDBMS you are using, I think that this (ugly) query would work on most of them:
SELECT Name + ' ' + CAST(Season AS VARCHAR(4)) + ' ' +
CAST(Games AS VARCHAR(4)) + ' games played ' +
CAST(Goals AS VARCHAR(4)) + ' goals scored' AS YourColumn
FROM ( SELECT Season, Name, SUM(Goals) AS Goals, COUNT(*) AS Games
FROM ( SELECT Season, Name1 AS Name, Goal1 AS Goals
FROM YourTable
UNION ALL
SELECT Season, Name2 AS Name, Goal2 AS Goals
FROM YourTable
UNION ALL
SELECT Season, Name3 AS Name, Goal3 AS Goals
FROM YourTable) AS A
GROUP BY Season, Name) X
Disclaimer: It is an ugly query.
That's really convoluted, but you could write an in-line query that puts everything into a proper table format so then you can do your usual aggregations and grouping. Keep adding unions for 1 through x, depending on how many columns there are.
SELECT Season, Name, Sum(Goals)
FROM (SELECT Season, Name1 as Name, Goals1 as Goals
FROM table
UNION
SELECT Season, Name2 as Name, Goals2 as Goals
FROM table
UNION
SELECT Season, Name3 as Name, Goals3 as Goals
FROM table) newtable
GROUP BY Season, Name