MariaDB 查询 SUM() OVER (PARTITION BY)
Posted
技术标签:
【中文标题】MariaDB 查询 SUM() OVER (PARTITION BY)【英文标题】:MariaDB Query SUM() OVER (PARTITION BY) 【发布时间】:2021-12-29 14:34:49 【问题描述】:我创建了一个查询,它根据某些条件(日期、isSpecial、isFirst、小时)对行进行不同的计数。 这是查询:
WITH test AS
(
SELECT customer_id, performance.id, performance_id,
Name, Date as zDate, Date, isSpecial, isFirst, hour
FROM recording
INNER JOIN performance ON performance_id = performance.id
)
SELECT id, Date, Name, isSpecial, isFirst, hour,
IF(NOT isSpecial AND NOT isFirst AND hour,
(SELECT SUM(CASE WHEN NOT isFirst AND NOT isSpecial
AND hour AND Date <= zDate
THEN 1 ELSE 0 END)
FROM recording
INNER JOIN performance ON recording.performance_id = performance.id
WHERE customer_id = 1
),
IF(isSpecial AND NOT isFirst AND hour,
(SELECT CONCAT('P',SUM(CASE WHEN NOT isFirst
AND isSpecial AND hour AND Date <= zDate
THEN 1 ELSE 0 END))
FROM recording
INNER JOIN performance ON recording.performance_id = performance.id
WHERE customer_id=1
),
IF(isFirst,'First','-')
)
) AS myTest
FROM test
WHERE customer_id = 1
ORDER BY Date
结果:
查询为我提供了一个 customer_id 的所需结果,而无需我设置变量。
我现在已经用 SUM() OVER (PARTITION BY customer_id) 试验了很长时间,但这总是导致“子查询返回多个记录”。
...
(SELECT CONCAT('P', SUM(CASE WHEN NOT isErst AND isProbatorik
AND therapiestunde AND Datum <= zDatum
THEN 1 ELSE 0 END)
OVER (PARTITION BY customer_id))
FROM leistungserfassung
INNER JOIN leistung ON leistungserfassung.Leistung_id = leistung.id),
...
是否可以将此总和扩展到所有 customer_id,以便对于每个 customer_id 总是再次汇总?
【问题讨论】:
不要为此使用相关子查询。只需在外部选择列表中使用 SUM(...) OVER (PARTITION BY customer_id ....) AS xxx 。很可能,您甚至都不需要 CTE 术语。 没有CREATE TABLE
语句很难测试。您的 SQL 不限定 每个 列引用,因此我们不知道哪个表包含每一列。
SUM(CASE WHEN boolean_expression THEN 1 ELSE 0 END)
可以简写为SUM(boolean_expression)
请显示想要的结果。
【参考方案1】:
这只是猜测,没有关于您的架构/表的足够详细信息:
试试这个(使用 mysql 8.0、MariaDB 10.6、10.5、10.4 等):
注意:如果您想要一个正在运行的 SUM,只需在窗口规范中添加一个 ORDER BY Date
子句(或类似的东西)。根据您的实际要求,可以删除显式日期逻辑。没有一点数据和预期的结果,很难判断。
The fiddle
WITH test AS (
SELECT customer_id, performance.id, performance_id
, Name, Date as zDate, Date, isSpecial, isFirst, hour
FROM recording
JOIN performance
ON performance_id = performance.id
)
SELECT id, Date, Name, isSpecial, isFirst, hour
, CASE WHEN NOT isSpecial AND NOT isFirst AND hour
THEN SUM(CASE WHEN NOT isFirst AND NOT isSpecial AND hour AND Date <= zDate THEN 1 ELSE 0 END) OVER w
WHEN isSpecial AND NOT isFirst AND hour
THEN CONCAT('P', SUM(CASE WHEN NOT isFirst AND isSpecial AND hour AND Date <= zDate THEN 1 ELSE 0 END) OVER w)
WHEN isFirst
THEN 'First'
ELSE '-'
END AS myTest
FROM test
WINDOW w AS (PARTITION BY customer_id)
ORDER BY customer_id, Date
;
将运行SUM
(Date
)行为添加到窗口函数并删除显式Date <= zDate
逻辑:
WITH test AS (
SELECT customer_id, performance.id, performance_id
, Name, Date, isSpecial, isFirst, hour
FROM recording
JOIN performance
ON performance_id = performance.id
)
SELECT id, Date, Name, isSpecial, isFirst, hour
, CASE WHEN NOT isSpecial AND NOT isFirst AND hour
THEN SUM(CASE WHEN NOT isFirst AND NOT isSpecial AND hour THEN 1 ELSE 0 END) OVER w
WHEN isSpecial AND NOT isFirst AND hour
THEN CONCAT('P', SUM(CASE WHEN NOT isFirst AND isSpecial AND hour THEN 1 ELSE 0 END) OVER w)
WHEN isFirst
THEN 'First'
ELSE '-'
END AS myTest
FROM test
WINDOW w AS (PARTITION BY customer_id ORDER BY Date)
ORDER BY customer_id, Date
;
结果(没有数据):
id | Date | Name | isSpecial | isFirst | hour | myTest |
---|
设置(我确定这些表格不正确。问题未包含此详细信息):
CREATE TABLE recording ( id int, performance_id int, customer_id int );
CREATE TABLE performance (
id int, Name VARCHAR(20), Date date
, isSpecial int, isFirst int, hour int
);
【讨论】:
非常感谢!这对我来说非常有用!新年快乐!以上是关于MariaDB 查询 SUM() OVER (PARTITION BY)的主要内容,如果未能解决你的问题,请参考以下文章
SUM OVER PARTITION BY 2 最后一行相同的值
RESET SUM(AMT_FIELD) OVER(PARTITION BY UNIQUE FIELD ORDER BY ROWNUM)
使用 sum() over(partition by) 逐一计算行中的值
Oracle - SELECT DENSE_RANK OVER(ORDER BY、SUM、OVER 和 PARTITION BY)