How to use MySQL and count and rank - mysql

I'm a MS-SQL Developer, now I use this query (MySQL) ↓
SELECT A.place_idx,A.place_id,B.TODAY_CNT,C.TOTAL_CNT FROM CUSTOM_LIST
AS A
INNER JOIN
(SELECT place_id,COUNT(place_id) AS TODAY_CNT from COUNT_TABLE where DATE(place_date) = DATE(NOW()) GROUP BY place_id)
AS B ON B.place_id=A.place_id
INNER JOIN
(SELECT place_id,COUNT(place_id) AS TOTAL_CNT from COUNT_TABLE GROUP BY place_id)
AS C ON C.place_id=A.place_id
The result is:
I want this:

Try somethink like this:
SELECT ..., C.TOTAL_CNT, (#r := #r + 1) AS rank FROM CUSTOM_LIST, (SELECT #r := 0) t
...
ORDER BY C.TOTAL_CNT DESC
Whole query:
SELECT A.place_idx,A.place_id,B.TODAY_CNT,C.TOTAL_CNT, (#r := #r + 1) AS rank
FROM CUSTOM_LIST AS A, (SELECT #r := 0) t
INNER JOIN
(SELECT place_id,COUNT(place_id) AS TODAY_CNT from COUNT_TABLE where DATE(place_date) = DATE(NOW()) GROUP BY place_id)
AS B ON B.place_id=A.place_id
INNER JOIN
(SELECT place_id,COUNT(place_id) AS TOTAL_CNT from COUNT_TABLE GROUP BY place_id)
AS C ON C.place_id=A.place_id
ORDER BY C.TOTAL_CNT DESC
What if we got two same values in Total_CNT?
Maybe something like this:
SELECT ..., (#last := C.TOTAL_CNT) AS TOTAL_CNT,
IF(#last = C.TOTAL_CNT, #r, #r := #r + 1) AS rank
FROM CUSTOM_LIST, (SELECT #r := 0, #last := -1) t
...

Updated
RANK() OVER (ORDER BY TOTAL_CNT DESC DESC) AS Rank
Here I got Another Very Good Solution.:
SELECT A.place_idx,A.place_id,B.TODAY_CNT,C.TOTAL_CNT, RANK() OVER (ORDER BY TOTAL_CNT DESC) AS Rank FROM CUSTOM_LIST
AS A
INNER JOIN
(SELECT place_id,COUNT(place_id) AS TODAY_CNT from COUNT_TABLE where DATE(place_date) = DATE(NOW()) GROUP BY place_id)
AS B ON B.place_id=A.place_id
INNER JOIN
(SELECT place_id,COUNT(place_id) AS TOTAL_CNT from COUNT_TABLE GROUP BY place_id)
AS C ON C.place_id=A.place_id

Related

How can i run this query for each user without using any function or procedure?

Here is my query which returns streaks for specific user=27:
SELECT MAX(sum) AS streak
FROM (
SELECT
game_date,
IF(points > 0, #sum:=#sum+1, #sum:=0) AS sum
FROM (
SELECT
game_date,
(SELECT COUNT(*) FROM point WHERE user_id = 27 AND bet_id = b.id AND goals > 0) AS points
FROM bet b
WHERE game_date < NOW()
ORDER BY game_date DESC
) t1, (SELECT #sum:=0) t2
) t;
What i try: it runs successfully on my local MySQL but gives an error on live phpMyAdmin that user_id is an unknown column in the where clause.
SELECT DISTINCT user_id,(
SELECT MAX(SUM) AS streak
FROM (
SELECT
game_date,
IF(points > 0, #sum:=#sum+1, #sum:=0) AS SUM
FROM (
SELECT
game_date,
(SELECT COUNT(*) FROM POINT WHERE user_id = p.user_id AND bet_id = b.id AND goals > 0) AS points
FROM bet b
WHERE game_date < NOW()
ORDER BY game_date DESC
) t1, (SELECT #sum:=0) t2
) t) AS streak FROM POINT p;
Without any sample data to test against, I may be way off the mark but give this a try:
SELECT user_id, MAX(SUM) AS streak
FROM (
SELECT b.game_date, u.user_id,
IF(
IFNULL(p.bet_id, 0) > 0,
IF(#prev_user = u.user_id, #sum := #sum + 1, #sum := 1),
#sum := 0
) AS SUM,
#prev_user := u.user_id
FROM bet b
CROSS JOIN (SELECT DISTINCT user_id FROM `POINT`) u
LEFT JOIN `POINT` p ON b.id = p.bet_id AND u.user_id = p.user_id AND p.goals > 0
JOIN (SELECT #sum:=0, #prev_user:=0) vars
WHERE b.game_date < NOW()
ORDER BY u.user_id ASC, b.game_date DESC
) t
GROUP BY user_id;
This is a variation of the gaps-and-islands problem.This query takes a different ("modern") approach, using the ROW_NUMBER() window function -
SELECT user_id, IFNULL(MAX(streak), 0)
FROM (
SELECT *, rn1 - rn2,
IF (
goals IS NOT NULL,
ROW_NUMBER() OVER (PARTITION BY user_id, rn1 - rn2 ORDER BY game_date),
NULL
) AS streak
FROM (
SELECT b.id AS bet_id, b.game_date, u.user_id, p.goals,
ROW_NUMBER() OVER (ORDER BY u.user_id, game_date) rn1,
ROW_NUMBER() OVER (PARTITION BY u.user_id, IF(p.bet_id IS NULL, 0, 1) ORDER BY game_date) rn2
FROM bet b
CROSS JOIN (SELECT DISTINCT user_id FROM `POINT`) u
LEFT JOIN `POINT` p ON b.id = p.bet_id AND u.user_id = p.user_id AND p.goals > 0
WHERE b.game_date < NOW()
) t1
) t2
GROUP BY user_id;

Mysql - dynamic UNION with multiple recieve ids

how to convert this multiple UNION to simple query?
number of artist_id is dynamic.
45,122,95
or
100,20
or
89,9449
or
22,495,700,98
....
(SELECT b.`id`, b.`id`, b.`date`, b.`artist`, b.`title`, b.`photo`
FROM `tags_mp3s` a
INNER JOIN `mp3s` b ON b.`id` = a.`mp3_id` AND a.`artist_id` = 45
ORDER BY b.`date` DESC
LIMIT 5)
UNION ALL
(SELECT b.`id`, b.`id`, b.`date`, b.`artist`, b.`title`, b.`photo`
FROM `tags_mp3s` a
INNER JOIN `mp3s` b ON b.`id` = a.`mp3_id` AND a.`artist_id` = 122
ORDER BY b.`date` DESC
LIMIT 5)
UNION ALL
(SELECT b.`id`, b.`id`, b.`date`, b.`artist`, b.`title`, b.`photo`
FROM `tags_mp3s` a
INNER JOIN `mp3s` b ON b.`id` = a.`mp3_id` AND a.`artist_id` = 95
ORDER BY b.`date` DESC
LIMIT 5)
.....
thanks
In MySQL, you can use variables:
SELECT ta.*
FROM (SELECT m.*,
(#rn := if(#a = t.artist_id, #rn + 1,
if(#a := t.artist_id, 1, 1)
)
) as rn
FROM tags_mp3s t INNER JOIN
mp3s m
ON m.id = t.mp3_id CROSS JOIN
(SELECT #rn := 0, #a := -1) params
WHERE t.artist_id IN (. . . )
ORDER BY t.artist_id, m.date DESC
) ta
WHERE rn <= 5;

Rank function in MySQL assign a rank

I need to assign a rank to TC5 not the id.
SELECT a.id, a.user_id, a.tc1, a.tc4, min(a.tc5), a.tc2, b.avatar, c.username, #curRank := #curRank + 1 AS Rank
FROM
treningove_casy a INNER JOIN
sn_users b ON a.user_id=b.id INNER JOIN
users c ON a.user_id=c.id , (SELECT #curRank := 0) r
WHERE a.tc2 LIKE 'Motokáry Modrice'
GROUP BY a.user_id
So how is the picture. Please help
The modified code
SELECT x.*, (#curRank := #curRank + 1) as Rank
FROM (SELECT a.id, a.user_id, a.tc1, a.tc4, min(a.tc5) as tc5,
a.tc2, b.avatar, c.username,
FROM sbhgl_chronoengine_chronoforms_datatable_treningove_casy a INNER JOIN
sbhgl_jsn_users b
ON a.user_id = b.id INNER JOIN
sbhgl_users c
ON a.user_id = c.id
WHERE a.tc2 LIKE 'Motokáry Modřice'
GROUP BY a.user_id
) x CROSS JOIN
(SELECT #curRank := 0) params
ORDER BY tc5 DESC;
SELECT a.id, a.user_id, a.tc1, a.tc4, a.tc2, b.avatar, c.username,
(select rank from (SELECT
IF (#score=s.tc5, #rank:=#rank, #rank:=#rank+1) rank,
#score:=s.tc5 tc5s
FROM treningove_casy s,
(SELECT #score:=0, #rank:=0) r
ORDER BY tc5 DESC) s ) as rank
FROM
treningove_casy a INNER JOIN
sn_users b ON a.user_id=b.id INNER JOIN
users c ON a.user_id=c.id , (SELECT #curRank := 0) r
WHERE a.tc2 LIKE 'Motokáry Modrice'
GROUP BY a.user_id
You can try above solution, Hope this will help you.
In MySQL, you typically use variables for ranks. In your case, you would use a subquery. I find that the variable method doesn't always work with GROUP BY:
SELECT x.*, (#curRank := #curRank + 1) as Rank
FROM (SELECT a.id, a.user_id, a.tc1, a.tc4, min(a.tc5) as tc5,
a.tc2, b.avatar, c.username,
FROM treningove_casy a INNER JOIN
sn_users b
ON a.user_id = b.id INNER JOIN
users c
ON a.user_id = c.id
WHERE a.tc2 LIKE 'Motokáry Modrice'
GROUP BY a.user_id
) x CROSS JOIN
(SELECT #curRank := 0) params
ORDER BY tc5 DESC;
Note: The use of table aliases is good. It is much easier to understand a query, though, if the aliases are abbreviations for the table names.

Mysql how limit left join results

I have two tables: songs and groups
i want limit the songs are match the group to 3
i tried this:
SELECT
groups.`IDgroup`,
groups.`name` AS g_name,
songs.`IDsong`,
songs.`name` AS s_name
FROM `groups`
LEFT OUTER JOIN songs ON (groups.`IDgroup` = songs.`IDgroup` LIMIT 3)
Put the limit out of parentheses:
SELECT
groups.`IDgroup`,
groups.`name` AS g_name,
songs.`IDsong`,
songs.`name` AS s_name
FROM `groups`
LEFT OUTER JOIN songs
ON groups.`IDgroup` = songs.`IDgroup`
LIMIT 3
It is generally not a good idea to put a limit on a query that does not explicitly order its results. The reason is that it could return different results over time.
So, you may want to consider adding an
ORDER BY groups.IDgroup, songs.IDsong
to your query (before the LIMIT 3), assuming that this combination is unique.
SELECT
g.`IDgroup`,
g.`name` AS g_name,
s.`IDsong`,
s.`name` AS s_name
FROM `groups` g
LEFT OUTER JOIN songs s
using ('idgroup')
LIMIT 3
This query will return the last 3 songs for each group:
SELECT
c.`IDgroup`,
c.`name` AS g_name,
s.`IDsong`,
s.`name` AS s_name
FROM
groups c
JOIN (
SELECT
IF(#C != c.IDgroup, #ROWNUM := 1, #ROWNUM := #ROWNUM +1) AS RN,
#C := c.IDgroup,
c.IDgroup,
s.IDsong,
s.name
FROM groups c
LEFT JOIN songs s ON c.`IDgroup` = s.`IDgroup`
CROSS JOIN (SELECT #C := '') t2
ORDER BY c.IDgroup ASC
) s ON c.`IDgroup` = s.`IDgroup`
JOIN JOIN (
SELECT IDgroup, MAX(rn) AS mx
FROM (
SELECT
IF(#C != c.IDgroup, #ROWNUM := 1, #ROWNUM := #ROWNUM +1) AS rn,
#C := c.IDgroup,
c.IDgroup
FROM groups c
LEFT JOIN songs s ON c.`IDgroup` = s.`IDgroup`
CROSS JOIN (SELECT #C := '') t2
ORDER BY c.IDgroup ASC
) t
GROUP BY IDgroup
) maxsong ON maxsong.IDgroup = c.IDgroup AND s.rn BETWEEN maxsong.mx-2 AND maxsong.mx
ORDER BY c.IDgroup ASC, s.`name` ASC
Fiddle: http://sqlfiddle.com/#!2/b65c3b/1
Take the LIMIT out of the parentheses:
SELECT
groups.`IDgroup`,
groups.`name` AS g_name,
songs.`IDsong`,
songs.`name` AS s_name
FROM `groups`
LEFT OUTER JOIN songs USING (`IDgroup`)
LIMIT 3

Rank not being determined properly

I'm using this query:
SELECT A.place_idx,A.place_id,B.TOTAL_CNT,(#r := #r + 1) AS rank FROM CUSTOM_LIST
AS A
INNER JOIN
(SELECT #r := 0)
AS C
INNER JOIN
(SELECT place_id,COUNT(place_id) AS TOTAL_CNT from COUNT_TABLE GROUP BY place_id)
AS B ON B.place_id=A.place_id order by B.TOTAL_CNT desc;
Which gives this result:
But I want this result:
How do I need to modify my query? What am I doing wrong?
SELECT *,(#r := #r + 1) AS rank FROM
(
SELECT A.place_idx,A.place_id,B.TOTAL_CNT FROM CUSTOM_LIST
AS A
INNER JOIN
(SELECT place_id,COUNT(place_id) AS TOTAL_CNT from COUNT_TABLE GROUP BY place_id)
AS B ON B.place_id=A.place_id order by B.TOTAL_CNT desc
) AS T, (SELECT #r := 0) AS tt
Your C.rank is getting calculated as they are processed, not after they are sorted. There is really no need for this data, anyways. Since you're sorting the rows by your metric, you know the first row is the first rank, etc. You can handle it on the programming side of things after you pull it out.
Alternatively, you can put what you have in an inner select, then do the rank after.