I have a MySQL statement that pulls back the top 15 scores from a table of users.
select #rownum:=#rownum+1 'rank', driverName, teamColour, totalScore, totalTime, didTyreChange from entries p, (SELECT #rownum:=0) r WHERE totalTime > 1000 and progress = 19 order by totalScore desc, totalTime asc limit 15
The conditions are, that the player must have completed all the questions (where progress = 19) and the final time must be more than 1 second (totalTime > 1000). The statement also returns their rank as a variable (#rownum:=#rownum+1 'rank').
The result of this query is the following
What I now want to do, is extend the results to only show a players top score. I have had a look at DISTINCT and GROUP BY but get these results with the following GROUP BY statement
select #rownum:=#rownum+1 'rank', driverName, teamColour, totalScore, totalTime, didTyreChange from entries p, (SELECT #rownum:=0) r WHERE totalTime > 1000 and progress = 19 group by driverName order by totalScore desc, totalTime asc limit 15
and nowhere with DISTINCT as I get error code 1064. I have tried both
select #rownum:=#rownum+1 'rank', DISTINCT(driverName), teamColour, totalScore, totalTime, didTyreChange from entries p, (SELECT #rownum:=0) r WHERE totalTime > 1000 and progress = 19 order by totalScore desc, totalTime asc limit 15
and
select DISTINCT driverName, #rownum:=#rownum+1 'rank', teamColour, totalScore, totalTime, didTyreChange from entries p, (SELECT #rownum:=0) r WHERE totalTime > 1000 and progress = 19 order by totalScore desc, totalTime asc limit 15
Neither provides the desired results. I'm wondering if there is an easy way to achieve this within the statement, or to do it on the PHP side of things instead.
The desired resultL
viper 1 9810
Maverick 2 25420
Racer roasty 3 28850
.. .
... 15
In other words, no user should appear in the results twice, only the quickest totalTime is displayed for each user.
Slimmed down SQLFiddle here http://sqlfiddle.com/#!2/36d3dc/7 (8000 char limit reached).
SELECT #i:=#i+1 rank, a.*
FROM
( SELECT x.*
FROM entries x
JOIN (SELECT drivername, MIN(totaltime) min_totaltime FROM entries WHERE progress = 19 AND totaltime > 1000 GROUP BY drivername) y
ON y.drivername = x.drivername
AND y.min_totaltime = x.totaltime
) a
, (SELECT #i:=0) i
ORDER
BY totalScore desc, totalTime asc;
http://sqlfiddle.com/#!2/36d3dc/17
If I understood your problem correctly then below query will help you:
select *,#rownum:=#rownum+1 as 'rank' from (select * from (select driverName, teamColour, totalScore, totalTime, didTyreChange from entries p WHERE totalTime > 1000 and progress = 19 order by totalScore desc, totalTime asc )a group by driverName)c , (select #rownum:=0)f
This should do:
select #rownum:=#rownum+1 'rank', driverName, totalScore, MIN(totalTime)
from entries p, (SELECT #rownum:=0) r
WHERE totalTime > 1000 and progress = 19
group by driverName
order by totalScore desc, totalTime asc
http://sqlfiddle.com/#!2/36d3dc/20/0
Related
SELECT e.emp_id, concat(e.firstname,' ', e.middlename,' ',e.lastname) as EmployeeName ,
(select * from mst_attendance where status='Present' AND a.current_date > '#2008-09-29%#' GROUP BY substr('emp_id',0,5) HAVING COUNT(*)>1 ORDER BY a.emp_id='5') as PresentDays,
a.emp_id, a.current_date, a.status, a.in_time, a.out_time FROM mst_attendance a
INNER JOIN mst_employee e ON a.emp_id=e.emp_id where e.status='active'
and e.flag='Y' and e.role='employee' and e.emp_id='5' ORDER BY a.created asc LIMIT 1
Here I want to know the present days of an employee. But I get the error:
1241 - Operand should contain 1 column(s)..
Instead of
(select * from mst_attendance where status='Present' AND a.current_date > '#2008-09-29%#' GROUP BY substr('emp_id',0,5) HAVING COUNT(*)>1 ORDER BY a.emp_id='5') as PresentDays
The query should be something like
(select column_name from mst_attendance where status='Present' AND a.current_date > '#2008-09-29%#' GROUP BY substr('emp_id',0,5) HAVING COUNT(*)>1 ORDER BY a.emp_id='5') as PresentDays
I have 2 tables;
banner_views (id, b_id, b_date)- this record a banner view every time it gets displayed
banners_dynamic (id, status, static_iname, static_keywords, static_url, static_alt, static_type, static_image, b_views, b_clicks) - stores the banner data
I would like to select 3 banners_dynamic results which have had the least views in the last 7 days.
I did put somethign together (see below) but I realised it was grabbing the total views for all banner rather than uniquely by id.
SELECT *,
(SELECT COUNT(*) FROM banner_views v WHERE v.b_date >= DATE(NOW()) - INTERVAL 7 DAY) as post_count
FROM banners_dynamic b
WHERE static_keywords LIKE '%test%' AND b.status='1' AND b.static_type='1'
ORDER BY post_count ASC LIMIT 3
Can anyone point me in the correct direction?
You must join both banners_dynamic table and your subquery with corresponding banner IDs:
SELECT
b.*, p.b_count
FROM
banners_dynamic b
INNER JOIN (
SELECT
b_id,
COUNT(*) AS b_count
FROM
banner_views v
WHERE
v.b_date >= DATE(NOW() - INTERVAL 7 DAY)
GROUP BY
b_id
) p on p.b_id = b.id
WHERE
b.static_keywords LIKE '%test%'
AND b.`status` = '1'
AND b.static_type = '1'
ORDER BY
p.b_count ASC
LIMIT 3
UPDATE: You can do it even without subquery:
SELECT
b.*, COUNT(v.b_id) AS b_count
FROM
banners_dynamic b
INNER JOIN banner_views v ON v.b_id = b.id
WHERE
v.b_date >= DATE_ADD(NOW(), INTERVAL - 7 DAY)
AND b.static_keywords LIKE '%test%'
AND b.`status` = '1'
AND b.static_type = '1'
GROUP BY
v.b_id
ORDER BY
b_count ASC
LIMIT 3;
If you want to include banners without any views (count=0) then you must do a LEFT JOIN:
SELECT
b.*, COUNT(v.b_id) AS b_count
FROM
banners_dynamic b
LEFT JOIN banner_views v ON v.b_id = b.id
AND v.b_date >= DATE_ADD(NOW(), INTERVAL - 7 DAY)
WHERE
b.static_keywords LIKE '%test%'
AND b.`status` = '1'
AND b.static_type = '1'
GROUP BY
v.b_id
ORDER BY
b_count ASC
LIMIT 3;
I want to select SUM of last 200,100 and 50 rows of close price from a table in a single query.
given below is the query for 200 rows.
SELECT SUM(Close_price) as tot200 FROM cash_data ORDER BY date_added LIMIT 0,200
can anyone help me with this.
You can use sub queries -
SELECT
(SELECT SUM(Close_price) FROM cash_data ORDER BY date_added LIMIT 0,200) as tot200,
(SELECT SUM(Close_price) FROM cash_data ORDER BY date_added LIMIT 0,100) as tot100,
(SELECT SUM(Close_price) FROM cash_data ORDER BY date_added LIMIT 0,50) as tot50
To make it in a single select without any subselects you can use a ranking varaible and sum conditionally
SELECT #rank := #rank + 1,
SUM(case when #rank <= 50 then Close_price else 0 end) as top_50_sum,
SUM(case when #rank <= 100 then Close_price else 0 end) as top_100_sum,
SUM(case when #rank <= 200 then Close_price else 0 end) as top_200_sum
FROM cash_data
cross join (select #rank := 0) r
ORDER BY date_added
LIMIT 0,200
Thanks for all the replies. Actually both the answers are working but i choose the second one and made some changes for my need. Below is the final query
SELECT
(SELECT SUM(Close_price)/200 FROM (SELECT Close_price FROM cash_data WHERE SERIES='$series' AND SYMBOL='$symbol' AND date_added <= '$date' ORDER BY date_added DESC LIMIT 0,200) as tot200) as avg200,
(SELECT SUM(Close_price)/100 FROM (SELECT Close_price FROM cash_data WHERE SERIES='$series' AND SYMBOL='$symbol' AND date_added <= '$date' ORDER BY date_added DESC LIMIT 0,100) as tot100) as avg100,
(SELECT SUM(Close_price)/50 FROM (SELECT Close_price FROM cash_data WHERE SERIES='$series' AND SYMBOL='$symbol' AND date_added <= '$date' ORDER BY date_added DESC LIMIT 0,50) as tot50) as avg50
Thank you all.
I have 3 tables as below in MySQL:
user: id username ...
post: id user_id title ....
user_post_like: id post_id user_id like_date (every like in a separate row)
Every user can send and like posts.
Now I wanna get the specified user daily rank according to the number of likes(from user_post_like table) that the user's posts got in the last 24 hours using an SQL command.
Maybe using count command for counting the users that have more likes than the specified user.
select u.username, count(l.id) as likes
from user_post_like l
join `user` u on u.od = l.user_id
where now() - interval 24 hour >= l.like_date
group by u.id, u.username
order by count(l.id) desc
and if you need a rank number too, you can do
select u.username, count(l.id) as likes, #rank := #rank + 1 as rank
from user_post_like l
join `user` u on u.od = l.user_id
cross join (select #rank := 0) r
where now() - interval 24 hour >= l.like_date
group by u.id, u.username
order by count(l.id) desc
I have the following query which works... but I need some changes:
SELECT
p.pid,
p.name,
GROUP_CONCAT( gC.leaguepoints ORDER BY leaguepoints DESC ) AS leaguepoints
FROM
golf_player p
LEFT JOIN
golf_card gC ON
p.pid = gC.pid
GROUP BY
p.pid
ORDER BY
p.name
DESC
What I really want is another property returned called totalleaguepoints which is a SUM of the most recent 20 league points in my table.
How do I add a limit to a group_concat?
It might be something like this?
SELECT
p.pid,
p.name,
GROUP_CONCAT( gC.leaguepoints ORDER BY leaguepoints DESC ) AS leaguepoints,
SUM(
SELECT
gC2.leaguepoints
FROM
golf_card gC2
WHERE
gC2.pid = p.pid
ORDER BY
leaguepoints
DESC
LIMIT 20
) AS totalleaguepoints
FROM
golf_player p
LEFT JOIN
golf_card gC ON
p.pid = gC.pid
GROUP BY
p.pid
ORDER BY
p.name
DESC
P.S, the above query does not run
Do you want just the top 20 league points for each player in the group_concat as well as the sum?
If so maybe use user variables:-
SELECT
p.pid,
p.name,
GROUP_CONCAT( gC.leaguepoints ORDER BY leaguepoints DESC ) AS leaguepoints,
SUM(gC.leaguepoints) AS totalleaguepoints
FROM golf_player p
LEFT JOIN
(
SELECT pid, leaguepoints, #Sequence:=IF(#PrevPid = pid, #Sequence + 1, 0) AS aSequence, #PrevPid := pid
FROM
(
SELECT pid, leaguepoints
FROM golf_card
ORDER BY pid, leaguepoints DESC
) Sub1
CROSS JOIN (SELECT #PrevPid := 0, #Sequence := 0) Sub2
) gC
ON p.pid = gC.pid AND aSequence < 20
GROUP BY p.pid
ORDER BY p.name DESC