使用按多列分组时可以得到完整的行吗?
Can I get the full rows when using group by multiple columns?
如果 table 中的日期、项目和类别相同,
我想将其视为同一行,其中 return n 行(例如:如果 n 为 3,则限制为 0、3)。
------------------------------------------
id | date | item | category | ...
------------------------------------------
101 | 20220201| pencil | stationery | ... <---
------------------------------------------ | treat as same result
105 | 20220201| pencil | stationery | ... <---
------------------------------------------
120 | 20220214| desk | furniture | ...
------------------------------------------
125 | 20220219| tongs | utensil | ... <---
------------------------------------------ | treat as same
129 | 20220219| tongs | utensil | ... <---
------------------------------------------
130 | 20220222| tongs | utensil | ...
预期结果(如果 n 为 3)
-----------------------------------------------
id | date | item | category | ... rank
-----------------------------------------------
101 | 20220201| pencil | stationery | ... 1
-----------------------------------------------
105 | 20220201| pencil | stationery | ... 1
-----------------------------------------------
120 | 20220214| desk | furniture | ... 2
-----------------------------------------------
125 | 20220219| tongs | utensil | ... 3
-----------------------------------------------
129 | 20220219| tongs | utensil | ... 3
问题是我还必须带上每个组的值。
如果我只有一列作为分组依据,我可以将 id 值与 origin table 进行比较,但我不知道如何处理多个列。
有什么办法可以解决这个问题吗?
作为参考,我使用用户变量将其与以前的值进行比较,
无法使用,因为持续时间很慢
SELECT
*,
IF(@prev_date=date and @prev_item=item and @prev_category=category,@ranking, @ranking:=@ranking+1) AS sameRow,
@prev_item:=item,
@prev_date:= date,
@prev_category:=category,
@ranking
FROM ( SELECT ...
我使用的是Mysql 8.0版本,id值不是一个连续的数字,因为我必须先排序再分组。
如果我没理解错的话,你可以尝试使用 dense_rank
window 函数并设置 order by
为你期望的列
如果date
列可以代表订单号我会放在第一位。
SELECT *
FROM (
SELECT *,dense_rank() OVER(ORDER BY date, item, category) rnk
FROM T
) t1
Window 函数在这种情况下非常有用。但对于我们这些仍在使用 MySQL 5.7 的人来说,row_number 等功能不存在,我们不得不求助于使用用户变量并每次在主语句之前重置该值,或者直接在语句中定义用户变量。
方法一
set @row_id=0; -- remember to reset the row_id to 0 every time before the main query below
select id,date,item,category,rank from testtb join
(
select date,item,category, (@row_id:=@row_id+1) as rank
from
(select date,item,category from testtb group by date,item,category) t1
) t2
using(date,item,category);
方法二
select id,date,item,category,rank from testtb join
(
select date,item,category, (@row_id:=@row_id+1) as rank
from
(select date,item,category from testtb group by date,item,category) t1, (select @row_id := 0) as n
) t2
using(date,item,category);
如果 table 中的日期、项目和类别相同, 我想将其视为同一行,其中 return n 行(例如:如果 n 为 3,则限制为 0、3)。
------------------------------------------
id | date | item | category | ...
------------------------------------------
101 | 20220201| pencil | stationery | ... <---
------------------------------------------ | treat as same result
105 | 20220201| pencil | stationery | ... <---
------------------------------------------
120 | 20220214| desk | furniture | ...
------------------------------------------
125 | 20220219| tongs | utensil | ... <---
------------------------------------------ | treat as same
129 | 20220219| tongs | utensil | ... <---
------------------------------------------
130 | 20220222| tongs | utensil | ...
预期结果(如果 n 为 3)
-----------------------------------------------
id | date | item | category | ... rank
-----------------------------------------------
101 | 20220201| pencil | stationery | ... 1
-----------------------------------------------
105 | 20220201| pencil | stationery | ... 1
-----------------------------------------------
120 | 20220214| desk | furniture | ... 2
-----------------------------------------------
125 | 20220219| tongs | utensil | ... 3
-----------------------------------------------
129 | 20220219| tongs | utensil | ... 3
问题是我还必须带上每个组的值。 如果我只有一列作为分组依据,我可以将 id 值与 origin table 进行比较,但我不知道如何处理多个列。
有什么办法可以解决这个问题吗?
作为参考,我使用用户变量将其与以前的值进行比较, 无法使用,因为持续时间很慢
SELECT
*,
IF(@prev_date=date and @prev_item=item and @prev_category=category,@ranking, @ranking:=@ranking+1) AS sameRow,
@prev_item:=item,
@prev_date:= date,
@prev_category:=category,
@ranking
FROM ( SELECT ...
我使用的是Mysql 8.0版本,id值不是一个连续的数字,因为我必须先排序再分组。
如果我没理解错的话,你可以尝试使用 dense_rank
window 函数并设置 order by
为你期望的列
如果date
列可以代表订单号我会放在第一位。
SELECT *
FROM (
SELECT *,dense_rank() OVER(ORDER BY date, item, category) rnk
FROM T
) t1
Window 函数在这种情况下非常有用。但对于我们这些仍在使用 MySQL 5.7 的人来说,row_number 等功能不存在,我们不得不求助于使用用户变量并每次在主语句之前重置该值,或者直接在语句中定义用户变量。
方法一
set @row_id=0; -- remember to reset the row_id to 0 every time before the main query below
select id,date,item,category,rank from testtb join
(
select date,item,category, (@row_id:=@row_id+1) as rank
from
(select date,item,category from testtb group by date,item,category) t1
) t2
using(date,item,category);
方法二
select id,date,item,category,rank from testtb join
(
select date,item,category, (@row_id:=@row_id+1) as rank
from
(select date,item,category from testtb group by date,item,category) t1, (select @row_id := 0) as n
) t2
using(date,item,category);