Select columns from a table and count a value from another table - sql

I have the following tables:
table_user
id
name
1
Arnold
2
Wesley
3
Abel
4
Harry
5
Cristiano
table_post
fk_user is from user who created the post
id
fk_user
title
description
1
2
Movie
I like horror movies
2
4
Music
Music is essential to my days
3
4
Soccer
The World Cup is coming!
table_post_like
fk_user is from user who liked the post
fk_post
fk_user
1
1
1
3
1
4
1
5
2
2
3
3
3
1
I need to select all posts liked by user Arnold (id 1) with all columns from tb_post and number of likes. The result would be something like that:
id
fk_user
title
description
likes
1
2
Movie
I like horror movies
4
3
4
Soccer
The World Cup is coming!
2
I tried this but the number of likes is not correct
SELECT TP.*, COUNT(TPL.fk_post) AS likes
FROM table_post AS TP
RIGHT JOIN table_post_like AS TPL
ON TP.id = TPL.fk_post
WHERE TPL.fk_user = 1
GROUP BY TP.id

Do this
SELECT table_post.*, t.occurence FROM table_post
JOIN
(SELECT fk_post, COUNT(fk_user) as occurence FROM table_post_like WHERE fk_post IN(SELECT fk_post FROM table_post_like WHERE fk_user = 1)
GROUP BY fk_post) as t ON t.fk_post = table_post.id
Query above returns the value as expected
id
fk_user
title
description
likes
1
2
Movie
I like horror movies
4
3
4
Soccer
The World Cup is coming!
2
Check db fiddle here

Related

create pivot table using sql

I have a database called player.db
These database has two tables.
The tables called person and the other is called match.
person table is
Player_ID
Player
Country
1
Lionel Messi
Argentina
2
Luis Suarez
Uruguay
3
Neymar
Brazil
match table is
Match _ID
Game
Player_ID
Date
Season
1
Uruguay-Paraguay
2
5/3/2019
1
2
Uruguay-Chile
2
19/3/2019
1
3
Argentina-Chile
1
22/3/2019
1
4
Brazil-Guyana
3
3/4/2019
1
5
Brazil-USA
3
1/6/2020
2
6
Brazil-Belize
3
3/7/2020
2
7
Brazil-Suriname
3
5/7/2020
2
8
Argentina-USA
1
8/8/2020
2
9
Argentina-Canada
1
3/3/2021
3
10
Argentina-Grenada
1
8/3/2021
3
11
Uruguay-Suriname
2
7/4/2021
3
12
Uruguay-Mexico
2
2/2/2022
4
13
Uruguay-Jamaica
2
4/2/2022
4
14
Brazil-Ecuador
3
5/2/2022
4
My pivot table should look like these:
Season
Player
1
Luis Suarez
2
Neymar
3
Lionel Messi
4
Luis Suarez
I want a sql code which create a pivot table which shows which player played most with topscore in which season year. For example Luis Suarez occured most in season 1.
I started coding in sql, but got not the desired solution
SELECT Player_ID, COUNT(*)FROM match GROUP BY Player_ID HAVING COUNT(*) max
The problem is I got an error and it doesn't create a pivot table which show which player played most in which season.
Join the tables, group by season and player to get the number of matches for each player and use FIRST_VALUE() window function to pick the top player of each season:
SELECT DISTINCT m.Season,
FIRST_VALUE(p.Player) OVER (PARTITION BY m.Season ORDER BY COUNT(*) DESC) Player
FROM match m INNER JOIN person p
ON p.Player_ID = m.Player_ID
GROUP BY m.Season, m.Player_ID;
See the demo.
Your clause HAVING count(*) max may cause the error.
The solution may depend on the relational data base you use. Here is a solution with postgresql :
SELECT DISTINCT ON (Season)
m.season, p.player, count(*) AS count
FROM match AS m
INNER JOIN player AS p ON p.player_ID = m.Player_ID
GROUP BY m.Season, p.Player_ID, p.player
ORDER BY m.Season ASC, count DESC
see dbfiddle

How to write SQL subqueries with count?

I'm using mysql. I want to count the minimum, maximum, and average number of different tags per movie from one table.
Exclude the duplicate:
same tag given by the same user to the same movie
same tag given by different users to the same movie
Example: table 'tags'
userId
movieId
tag
1
1
crime
1
2
dark
1
2
dark
2
2
greed
2
2
dark
3
3
music
3
3
dance
3
3
quirky
4
3
dance
4
3
quirky
Expect result:
movieId
Min_Tag
Max_Tag
Avg_Tag
1
1
1
1
2
1
2
0.66...
3
1
2
0.6
I try to write query like below, but it shows an error.
SELECT
DISTINCT movieId,
MIN(COUNT(DISTINCT tag) AS Min_Tag,
MAX(COUNT(DISTINCT tag) AS Max_Tag,
AVG(COUNT(DISTINCT tag) AS Avg_Tag,
FROM (
SELECT userId,movieId,tag
FROM tags
GROUP BY userId, movieId, tag
) AS non_dup
GROUP BY movieId;
You have to rewrite your query
First you need the count per tag and movie
and fromm that you can calculate min max and avg
SELECT
movieId,
MIN(count_tag) AS Min_Tag,
MAX(count_tag) AS Max_Tag,
AVG(count_tag) AS Avg_Tag
FROM
(SELECT movieId,tag, count(*) count_tag
FROM tags
GROUP BY movieId, tag) non_dup
GROUP BY movieId
movieId
Min_Tag
Max_Tag
Avg_Tag
1
1
1
1.0000
2
1
3
2.0000
3
1
2
1.6667
fiddle

Delete Group of Records based on Group Statistic

I have the following two example tables
Teams
Team ID
Team Name
1
Bears
2
Tigers
3
Lions
4
Sharks
Players
Player ID
Name
Team ID
Playtime
1
John
1
5
2
Adam
1
4
3
Smith
1
5
4
Michelle
2
5
5
Stephanie
2
10
6
David
2
10
7
Courtney
2
2
8
Frank
2
7
9
Teresa
2
1
10
Michael
3
3
11
May
4
1
12
Daniel
4
1
13
Lisa
4
4
I need a select statement with the following criteria
Select all teams with less than 4 players
Figure out the total playtime for all players on those teams and sort the resulting table based on this in descending order
Based on the example given, I would want a table that looks like this:
Teams
Team Name
Num Players
Total Playtime
Bears
3
14
Sharks
3
6
Lions
1
3
Finally, I want to cut all even rows from the previous table, so the final table would look like:
Team Name
Num Players
Total Playtime
Bears
3
14
Lions
1
3
You may try the following:
Query #1
SELECT
t."Team Name",
COUNT(p."Player ID") as "Num Players",
SUM(p."Playtime") as "Total Playtime"
FROM
teams t
LEFT JOIN
players p ON t."Team ID"=p."Team ID"
GROUP BY
t."Team Name"
HAVING
COUNT(p."Player ID") < 4
ORDER BY
SUM(p."Playtime") DESC;
Team Name
Num Players
Total Playtime
Bears
3
14
Sharks
3
6
Lions
1
3
Query #2
SELECT
t1."Team Name",
t1."Num Players",
t1."Total Playtime"
FROM (
SELECT
ROW_NUMBER() OVER (ORDER BY SUM(p."Playtime") DESC) as rn,
t."Team Name",
COUNT(p."Player ID") as "Num Players",
SUM(p."Playtime") as "Total Playtime"
FROM
teams t
LEFT JOIN
players p ON t."Team ID"=p."Team ID"
GROUP BY
t."Team Name"
HAVING
COUNT(p."Player ID") < 4
) t1
WHERE MOD(rn,2)=1
ORDER BY rn;
Team Name
Num Players
Total Playtime
Bears
3
14
Lions
1
3
View on DB Fiddle
Let me know if this works for you.

SQL get sum of multiple averages

I have a table with Songs, users and users rating of the song.
ratings.*
userID
songID
rating
95
1
8
12
1
6
95
1
8
13
1
6
81
2
3
42
2
1
51
3
6
22
3
6
I also have a table thet matches songID's and artists.
songs.*
songID
artist
1
Michal Jackson
2
Queen
What I need is to get the average rating of each song, and then take the sum to find a total rating for the artist.
So here, ill try to show with the input, Michel Jackson.
SELECT SUM( AVG(ratings.rating WHERE songID=1) + AVG(ratings.rating WHERE songID=3) )
Wanted output
Input, artist
Output, total rating
"Michal Jackson"
13
"Queen"
2
Every answer is really appreciated, thank you.
You could use a derived table (using a subquery as a table):
SELECT
songID
, SUM(average_rating) AS total_rating
FROM (
SELECT
songID
, artist
, AVG(rating) AS average_rating
FROM songs
GROUP BY songID
) AS song_ratings
GROUP BY artist

What will be the query to get Student names for every individual study group?

meetings which looks like this:
meeting_ID
place
1
A
2
B
3
C
study_groups which looks like this:
study_group_id
meeting_id (fk)
topic
1
1
Basics
2
2
Photography
3
1
Film
students which looks like this:
student_id
name
1
xyz
2
abc
2
pqr
group_members which looks like this:
study_group_id (fk)
student_id (fk)
2
10
1
1
2
5
3
15
1
9
3
2
3
11
A meeting has many study_groups and each study_groups has many students.
I want to find the student names in each group individually for meeting_id = 1.
Is that possible or not to do in the same query?
If not what should I do, please suggest me.
This is my present SQL query:
SELECT
study_groups.study_group_id,
(SELECT COUNT(*)
FROM group_members
WHERE study_groups.study_group_id = group_members.study_group_id) AS no_of_students,
study_groups.topic
FROM
study_groups
WHERE
study_groups.meeting_id = 1;
Now the table looks like:
study_group_id
no_of_student
topic
1
2
Basics
2
3
Photography
student_name column result in below is demo but I want the data as like this.
The result I expect:
study_group_id
no_of_student
topic
student_name
1
2
Basics
xyz, abc, pqr
2
3
Photography
abc, pqr
If you want the students in the study group and you are using Postgres, you can aggregate them into an array:
SELECT sgs.study_group_id,
(SELECT ARRAY_AGG(s.name)
FROM group_members gm JOIN
students s
ON gm.student_id = s.student_id
WHERE sg.study_group_id = gm.study_group_id
) AS student_names,
sg.topic
FROM study_groups sg
WHERE sg.meeting_id = 1;