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
;

将运行SUMDate)行为添加到窗口函数并删除显式Date &lt;= 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)

MariaDB over SSL 不工作,“证书验证失败”

如何在 mysql 5.7 中使用 sum over partition(无窗口函数)