I'm pretty new to SQL and I've been doing some exercises online to improve my query skills.
I was trying to solve this problem: https://www.hackerrank.com/challenges/contest-leaderboard/problem
I was able to solve it with the code below, but I was wondering if there's any way to simplify it/make it more efficient?
SELECT
id,
name,
total_score
FROM(
SELECT
id,
name,
SUM(sscore) as total_score
FROM(
SELECT
id,
name,
challenge_id,
MAX(score) as sscore
FROM(
SELECT
hacker_id as id,
name,
submission_id,
challenge_id,
score
FROM
Hackers
INNER JOIN
Submissions s USING(hacker_id)
ORDER BY
hacker_id,
challenge_id)a
GROUP BY id, name, challenge_id)b
GROUP BY id, name
ORDER BY total_score DESC, id ASC)c
WHERE total_score > 0;
You only need a join not two or three. For controling 0 values you can use HAVING clause.
SELECT a.hacker_id,a.name, SUM(a.mscore) from (
SELECT h.hacker_id,h.name, max(score) as mscore from Submissions s inner join hackers h on h.hacker_id=s.hacker_id group by h.hacker_id, challenge_id,h.name
) as a group by a.hacker_id,a.name
HAVING SUM(a.mscore) > 0
ORDER BY 3 DESC,
1 ASC
Here is what I tried and it submitted successfully .
SELECT b.hacker_id, b.name , c.total_score from (
SELECT a.hacker_id as hid, SUM(a.max_score) as total_score from (
SELECT hacker_id, max(score) as max_score from Submissions group by hacker_id, challenge_id
) as a group by a.hacker_id
) as c INNER JOIN Hackers b
ON b.hacker_id = c.hid
WHERE c.total_score > 0
ORDER BY c.total_score DESC,
b.hacker_id ASC
Related
How can i solve this question of hackerrank. I am quite confused an unable to move forward with this.
here is what i have tried
SELECT DISTINCT ACTIVITY FROM FRIENDS,
SELECT max(ACTIVITY) AS M
WHERE M = (SELECT NAME FROM Activities);
You can use window functions if your mysql version is 8 or above
select activity from (select activity, count(*) as cnt,
max(count(*)) over () as maximum_cnt,
min(count(*)) over () as minimum_cnt
from friends group by activity) mytable
where cnt not in (maximum_cnt, minimum_cnt);
I solved this using mysql
select activity
from
(select activity, count(activity) as cnt
from friends
group by activity
having cnt <> (select count(activity) from friends group by activity order by count(activity) limit 1)
and
cnt <> (select count(activity) from friends group by activity order by count(activity) desc limit 1)
) as x;
I like to solve tasks like this with left join and checking NULL:
SELECT
ACTIVITY,
SUM(1) AS Total
INTO #ActivityCount
FROM FRIENDS
GROUP BY ACTIVITY
SELECT
ActivityCount.ACTIVITY
FROM #ActivityCount
LEFT JOIN (SELECT MAX(ActivityCount.Total) AS Total FROM ActivityCount) AS MaxTotal
ON ActivityCount.Total = MaxTotal.Total
LEFT JOIN (SELECT MIN(ActivityCount.Total) AS Total FROM ActivityCount) AS MinTotal
ON ActivityCount.Total = MinTotal.Total
WHERE
MaxTotal.Total IS NULL
AND MinTotal.Total IS NULL
Here is what i did
Select ACTIVITY from Friends
group by ACTIVITY
having count(ACTIVITY) <> (select count1 from (select count(ACTIVITY)
count1 from Friends
group by (ACTIVITY)
order by count1 asc)
where rownum <= 1) and count(ACTIVITY) <> (select count2 from (select count(ACTIVITY) count2 from Friends group by (ACTIVITY) order by count2 desc) where rownum <= 1);
with temp as
(
select activity, count(id) as act_count from friends
group by activity
)
select activity from temp
where act_count not in (select max(act_count) from temp)
and act_count not in (select min(act_count) from temp);
I have a History table that represents messages that are stored by some sort of chat program.
It has a user id, message & datetime. (specified on: http://sqlfiddle.com/#!9/49fcefb/5)
Now, what I want is to have a result which contains:
The max amount of messages typed by date
What user has the most messages and howmany messages this user typed)
I got it working, but I find the query rather slow, I think its because of the last GROUP BY (GROUP BY b.cnt) as this will group over all the records found.
Query:
SELECT b.cnt as dayCount, a.cnt as userCount, a.userid as userId, b.date
FROM (
select date_added as date, user_id as userid, count(*) as cnt from history group by userid, day(date_added),month(date_added),year(date_added)
) a
INNER JOIN (
select date_added as date, count(*) as cnt from history group by day(date_added),month(date_added),year(date_added)
) b ON year(a.date) = year(b.date)
AND month(a.date) = month(b.date)
AND day(a.date) = day(b.date)
GROUP BY b.cnt
ORDER BY dayCount desc, userCount desc limit 10;
Can someone advice me on how to solve this? Maybe with another sort of query?
Thanks in advance!
You can try using windows function with Subquery to get the same result.
select SQ.daycount,SQ.usercount,SQ.user_id, SQ.date1 from (
select sum(count(Message)) over (partition by date(date_added)) as daycount, --to get max amount of msg by date
max(count(Message)) over (partition by date(date_added)) as maxuser, -- to identify user with most msg
count(Message) as usercount,
date(date_added) as date1,user_id from history
group by date1,user_id ) SQ
where SQ.usercount=SQ.maxuser
Check the Fiddle here
seems you are joining with wrong criteria.
first table is getting the # of users, 2nd table is getting the #of days per user_id. see dbfiddle
SELECT b.cnt as dayCount, a.cnt as userCount, a.userid as userId, b.date
FROM (
select
user_id as userid
, count(*) as cnt
from history
group by userid
) a
LEFT JOIN (
select cast(date_added as date) as date
, count(*) as cnt
, user_id as userid
from history
group by cast(date_added as date)
) b ON a.userid = b.userid
ORDER BY dayCount desc, userCount desc limit 10;
This is my customer table.
I want to group by emp_id alongwith the count. But Group By gets the 'first' record and not the 'newest' one.
I have tried various queries, like this
SELECT id, emp_id, COUNT( * ) AS count, created_at
FROM customer c
WHERE created_at = (
SELECT MAX( created_at )
FROM customer c2
WHERE c2.emp_id = c.emp_id
)
GROUP BY emp_id
ORDER BY created_at DESC
LIMIT 0 , 30
But cannot get the count. Please help.
Edit: this answer doesn't help to obtain count
Try joining to a subquery:
SELECT c1.id, c1.emp_id, c1.created_at, c2.cnt
FROM customer c1
INNER JOIN
(
SELECT emp_id, MAX(created_at) AS max_created_at, COUNT(*) AS cnt
FROM customer
GROUP BY emp_id
) c2
ON c1.emp_id = c2.emp_id AND c1.created_at = c2.max_created_at;
please try this
SELECT cust1.id, cust1.emp_id, cust1.created_at, cust2.cnt
FROM customer cust1
INNER JOIN
(
SELECT emp_id, MAX(created_at) AS max_created_at, COUNT(*) AS count
FROM customer
GROUP BY emp_id
) cust2
ON cust1.emp_id = cust2.emp_id AND cust1.created_at = cust2.max_created_at;
I am trying to solve this HackerRank SQL coding challenge. We have two tables, one called Hackers with columns hacker_id and name and another called Submissions with columns submission_date, submission_id, hacker_id, and score.
One query I submitted to solve the challenge was:
SELECT es.date, es.count, m.hacker_id, m.name, m.score
FROM
(
SELECT submission_date as date, COUNT(hacker_id) as count
FROM (
SELECT submission_date, COUNT(submission_id) as count, hacker_id
FROM Submissions
GROUP BY submission_date, hacker_id
) f
HAVING count >=1
) es
JOIN (
SELECT s.submission_date as date, s.hacker_id, h.name, s.score
FROM Submissions s
JOIN Hackers h ON h.hacker_id = s.hacker_id
JOIN (SELECT submission_date, MAX(score) as score FROM Submissions GROUP BY submission_date) foo ON foo.submission_date = s.submission_date
WHERE s.score = foo.score
) m
ON es.date = m.date
ORDER BY es.date
However, I got back the error:
ERROR 1140 (42000) at line 1: In aggregated query without GROUP BY, expression #1 of SELECT list contains nonaggregated column 'f.submission_date'; this is incompatible with sql_mode=only_full_group_by
This really confused me since I didn't use an aggregate function in my query. Why did the interpreter give this error, and what should I think about to resolve it?
There are two columns named count in first subquery. One is count of field submission_id and second is count of hacker_id. As I understood query needs to perform selection of submission_dates where count greater than or equal to 1. So depends on which count is presumed to be greater than or equal to 1, the query might be rewritten as following:
1) If it is needed that count(submission_id) greater than or equal to 1:
SELECT es.date, es.count, m.hacker_id, m.name, m.score
FROM
(
SELECT submission_date as date, COUNT(hacker_id) as count
FROM (
SELECT submission_date, COUNT(submission_id) as count, hacker_id
FROM Submissions
GROUP BY submission_date, hacker_id
) f
WHERE f.count >=1
GROUP BY submission_date
) es
JOIN (
SELECT s.submission_date as date, s.hacker_id, h.name, s.score
FROM Submissions s
JOIN Hackers h ON h.hacker_id = s.hacker_id
JOIN (SELECT submission_date, MAX(score) as score FROM Submissions GROUP BY submission_date) foo ON foo.submission_date = s.submission_date
WHERE s.score = foo.score
) m
ON es.date = m.date
ORDER BY es.date
2) the count(hacker_id) is greater than or equal to 1:
SELECT es.date, es.count, m.hacker_id, m.name, m.score
FROM
(
SELECT submission_date as date, COUNT(hacker_id) as count
FROM (
SELECT submission_date, COUNT(submission_id) as count, hacker_id
FROM Submissions
GROUP BY submission_date, hacker_id
) f
GROUP BY submission_date
HAVING count(hacker_id) >= 1
) es
JOIN (
SELECT s.submission_date as date, s.hacker_id, h.name, s.score
FROM Submissions s
JOIN Hackers h ON h.hacker_id = s.hacker_id
JOIN (SELECT submission_date, MAX(score) as score FROM Submissions GROUP BY submission_date) foo ON foo.submission_date = s.submission_date
WHERE s.score = foo.score
) m
ON es.date = m.date
ORDER BY es.date
The problem is that in subquery the aggregated function count(hacker_id) was used without "group by" section with column "submission_date" defined there as nonaggregated column.
Still I'm not sure that the sql-query is logically correct.
I wrote the following query to return the the records with the latest date.
select fs.company_id, max(fs.create_dt) as latestcreatedate
from field_sale fs
group by fs.company_id
order by fs.company_id
The query all works fine. But I need to retrieve the record with all related columns attached to it. Such as, id, title, desc and etc.
How can I retrieve the records with its corresponding columns?
Couple ways of doing so :
-- 1.
SELECT a.*
FROM field_sale a
INNER JOIN
(
select fs.company_id, max(fs.create_dt) as latestcreatedate
from field_sale fs
group by fs.company_id
)b
ON b.company_id = a.company_id AND b.latestcreatedate = a.create_dt
order by a.company_id;
-- 2.
SELECT b.* FROM
(
SELECT a.* , ROW_NUMBER()
OVER (PARTITION BY a.company_id ORDER BY a.create_dt DESC)
AS rn
FROM field_sale a
)b WHERE b.rn = 1
ORDER BY company_id
WITH t AS (
SELECT fs.company_id,
fs.create_dt AS latestcreatedate,
id,
title,
etc,
ROW_NUMBER() OVER ( PARTITION BY fs.company_id ORDER BY fs.create_dt DESC ) AS rowNum
FROM field_sale fs
)
SELECT t.company_id,
t.latestcreatedate,
t.id,
t.title,
t.etc
FROM t
WHERE t.rowNum = 1
ORDER BY t.company_id