I have this kind of query that need to limit by 3 in each 'region' group but it doesnt run as I expected. The 'row_number' seems not arranged accordingly. There must be some syntax I missed out or I didnt know. If anyone can help I dump the sql Here . MYSQL version 5.0
My query :
set @type = '';
set @num = 0;
SELECT locinvaisle.Area as ar,locinvaisle.Region as rg,custlist.CustomerName as cn,custlist.Custtype ct,
SUM(data2.quantity/1000) as mtcur,
@num := if(@type = locinvaisle.Region, @num + 1, 1) as dummy_1,
@type := locinvaisle.Region as dummy_2,
@num as row_number
FROM data2
INNER JOIN custlist ON data2.customeracc = custlist.Customeraccount
INNER JOIN locinvaisle ON data2.location = locinvaisle.Location
WHERE
date1 >= DATE_FORMAT('2018-06-11', '%Y-01-01') AND date1 <= DATE_FORMAT('2018-06-11', '%Y-%m-31')
AND
data2.unit = 'KG'
AND
data2.customeracc not in (select Customeraccount from custlist WHERE Custcat = 'bcsb')
AND
locinvaisle.Area = 'peninsular'
AND
custlist.Custtype = 'others'
GROUP BY locinvaisle.Region,custlist.CustomerName
HAVING row_number < 3
ORDER BY locinvaisle.Region,mtcur desc
Results :
Desired Results(From dummy database) :
You have to do the limiting as a full subquery ("derived table") before the group by is applied. Something along these lines:
SELECT
ar, rg, cn, ct, sum(quantity)
FROM (
SELECT
@row_num :=IF(@prev_value = locinvaisle.Region, @row_num + 1, 1)AS RowNumber
, locinvaisle.Area as ar
, locinvaisle.Region as rg
, custlist.CustomerName as cn
, custlist.Custtype ct
, data2.quantity
, @prev_value := locinvaisle.Region as dummy_2,
FROM data2
INNER JOIN custlist ON data2.customeracc = custlist.Customeraccount
INNER JOIN locinvaisle ON data2.location = locinvaisle.Location
CROSS JOIN (SELECT @row_num :=1, @prev_value :='') vars
WHERE date1 >= DATE_FORMAT('2018-06-11', '%Y-01-01') AND date1 <= DATE_FORMAT('2018-06-11', '%Y-%m-31')
AND data2.unit = 'KG'
AND data2.customeracc not in (select Customeraccount from custlist WHERE Custcat = 'bcsb')
AND locinvaisle.Area = 'peninsular'
AND custlist.Custtype = 'others'
ORDER BY locinvaisle.Region,mtcur desc
) d
WHERE rowNumber <= 3
GROUP BY ar, rg, cn, ct
ORDER BY ar, rg, cn, ct
NOTE: You need to apply an ORDER BY
within the subquery to facilitate the rownumber calculation, but despite this there is no guarantee that the final output will be in the desired order unless you apply a final order by clause.
Also please note that in future versions of MySQL (V8 and above) there should be a row_number()
function and over()
clause that can be used instead of the variables seen above.
In MySQL, you need to be careful when using variables. Two things are important:
So, try something like this:
SELECT x.*,
(@rn := IF(@r = la.Region, @num + 1,
IF(@r := la.Region, 1, 1)
)
) as rn
FROM (SELECT la.Area as ar, la.Region as rg, c.CustomerName as cn, c.Custtype ct,
SUM(data2.quantity/1000) as mtcur
FROM data2 d INNER JOIN
custlist c
ON d.customeracc = c.Customeraccount INNER JOIN
locinvaisle la
ON d.location = la.Location
WHERE date1 >= DATE_FORMAT('2018-06-11', '%Y-01-01') AND
date1 <= DATE_FORMAT('2018-06-11', '%Y-%m-31') AND
d.unit = 'KG' AND
d.customeracc not in (select Customeraccount from custlist cl WHERE cl Custcat = 'bcsb') AND
la.Area = 'peninsular' AND
c.Custtype = 'others'
GROUP BY la.Region, c.CustomerName
) x CROSS JOIN
(SELECT @r := 0, @rn := 0) params
HAVING rn <= 3;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.