我有一张桌子,看起来像:
select o.id, name, orderdate, o.ordervalue
from orders o
cross apply (select top 1 id, ordervalue from orders where name=o.name and orderdate=o.OrderDate order by ordervalue desc) oo
where o.id=oo.id
order by o.id
并且按组和日期排序。我想要一个额外的列来显示每个组的连续颜色'R'的顺序号。
必需的输出:
group date color
A 1-1-2019 R
A 1-2-2019 Y
B 1-1-2019 R
B 1-2-2019 Y
B 1-3-2019 Y
B 1-4-2019 R
B 1-5-2019 R
B 1-6-2019 R
我尝试将窗口函数用于按组和颜色列进行分区,但是它返回的输出在下面是不正确的。
错误的查询和输出:
group date color rank
A 1-1-2019 R 1
A 1-2-2019 Y null
B 1-1-2019 R 1
B 1-2-2019 Y null
B 1-3-2019 Y null
B 1-4-2019 R 1
B 1-5-2019 R 2
B 1-6-2019 R 3
我想知道它是否可以在SQL中使用,还是应该切换到另一种语言(例如Python)?
答案 0 :(得分:3)
使用用户变量可以保留排名和先前的值以产生结果:
CREATE TABLE tbl (
`group` VARCHAR(1),
`date` VARCHAR(8),
`color` VARCHAR(1)
);
INSERT INTO tbl
(`group`, `date`, `color`)
VALUES
('A', '1-1-2019', 'R'),
('A', '1-2-2019', 'Y'),
('B', '1-1-2019', 'R'),
('B', '1-2-2019', 'Y'),
('B', '1-3-2019', 'Y'),
('B', '1-4-2019', 'R'),
('B', '1-5-2019', 'R'),
('B', '1-6-2019', 'R');
set @seq := 0, @prev := 'B'
SELECT
*,
IF(color='R', @seq := IF(@prev = color, @seq + 1, 1), NULL) AS rank,
@prev := color as prev
FROM tbl
ORDER BY `group`, `date`
group | date | color | rank | prev
:---- | :------- | :---- | ---: | :---
A | 1-1-2019 | R | 1 | R
A | 1-2-2019 | Y | | Y
B | 1-1-2019 | R | 1 | R
B | 1-2-2019 | Y | | Y
B | 1-3-2019 | Y | | Y
B | 1-4-2019 | R | 1 | R
B | 1-5-2019 | R | 2 | R
B | 1-6-2019 | R | 3 | R
db <>提琴here
答案 1 :(得分:3)
这是使用窗口功能可以完成的方法。首先,我们创建一个CTE,该CTE具有一个标志,指示新的序列已开始,然后从中生成一个对序列号进行计数的标志。最后,我们对每个序列中的行进行计数以获得排名:
WITH cte AS (SELECT `group`, date, color,
COALESCE(color = LAG(color) OVER(ORDER BY `group`, date), 0) AS samecolor
FROM `table`),
sequences AS (SELECT `group`, date, color,
SUM(samecolor = 0) OVER (ORDER BY `group`, date) AS seq_num
FROM cte)
SELECT `group`, date, color,
ROW_NUMBER() OVER (PARTITION BY seq_num) AS `rank`
FROM sequences
ORDER BY `group`, date
输出:
group date color rank
A 1-1-2019 R 1
A 1-2-2019 Y 1
B 1-1-2019 R 1
B 1-2-2019 Y 1
B 1-3-2019 Y 2
B 1-4-2019 R 1
B 1-5-2019 R 2
B 1-6-2019 R 3
请注意,如果您希望将这些值Y
替换为NULL
,则此查询还会给出rank
值的排名:
CASE WHEN color = 'Y' THEN NULL
ELSE ROW_NUMBER() OVER (PARTITION BY seq_num)
END AS `rank`
答案 2 :(得分:1)
将window function row_number()
用于 Postgres 中的纯标准SQL解决方案-或任何现代RDBMS,甚至包括从版本8开始的MySQL:
vec2
multiplyv2(vec2 a, vec2 b) {
return a * b
}
vec3
multiplyv3(vec3 a, vec3 b) {
return a * b
}
....
这假定vec2 rotate(vec2 v, float angle) {
return rotation2d(angle) * v;
}
vec3 rotate(vec3 v, vec3 axis, float angle) {
return (rotation3d(axis, angle) * vec4(v, 1.0)).xyz;
}
被定义为SELECT grp, the_date, color
, row_number() OVER (PARTITION BY grp, color, part
ORDER BY the_date) AS rnk
FROM (
SELECT *
, row_number() OVER (PARTITION BY grp ORDER BY the_date, color)
- row_number() OVER (PARTITION BY grp, color ORDER BY the_date) AS part
FROM tbl
) sub
ORDER BY grp, the_date, color;
,重复将产生不确定的结果。
减去两个不同的行号将为每个孤岛计算一个不同的数字((grp, color, the_date)
)。然后,您可以再次运行UNIQUE
,现在再按子组进行分区。 Voilá。
要仅查看特定颜色的数字,在示例中为“ R”:
part
虽然基于集合的解决方案是RDBMS的要塞,并且通常更快,但是过程解决方案仅需要对此类问题进行一次扫描,因此,该plpgsql函数应实质上为 < em>更快 :
row_number()
致电:
SELECT grp, the_date, color, CASE WHEN color = 'R' THEN rnk END AS rnk
FROM (
<<query from above, without ORDER BY>>
) sub
ORDER BY grp, the_date, color;
db <>提琴here
在关系数据库中,循环并非总是错误的解决方案。
进一步阅读:
此外:“行”是这些行号的一个相当误导的名称,除非您有重复项应该排在同一位...