sql - SQL Server 中求和函数的工作方式

标签 sql sql-server sum window-functions

鉴于此表

CREATE TABLE Table1
(
    [Classroom] int,
    [CourseName] varchar(8),
    [Lesson] varchar(9),
    [StartTime] char(4),
    [EndTime] char(4)
);
    
INSERT INTO Table1
    ([Classroom], [CourseName], [Lesson], [StartTime], [EndTime])
VALUES
    (1001, 'Course 1', 'Lesson 1', '0800', '0900'),
    (1001, 'Course 1', 'Lesson 2', '0900', '1000'),
    (1001, 'Course 1', 'Lesson 3', '1000', '1100'),
    (1001, 'Course 1', 'Lesson 6', '1100', '1200'),
    (1001, 'Course 2', 'Lesson 10', '1100', '1200'),
    (1001, 'Course 2', 'Lesson 11', '1200', '1300'),
    (1001, 'Course 1', 'Lesson 4', '1300', '1400'),
    (1001, 'Course 1', 'Lesson 5', '1400', '1500');

还有我的查询

WITH A AS 
(
    SELECT 
        ClassRoom,
        CourseName,
        StartTime,
        EndTime,
        PrevCourse = LAG(CourseName, 1, CourseName) OVER (ORDER BY StartTime)
    FROM   
        Table1
), B AS 
(
    SELECT 
        ClassRoom,
        CourseName,
        StartTime, EndTime,
        Ranker = SUM(CASE WHEN CourseName = PrevCourse THEN 0 ELSE 1 END) 
                    OVER (ORDER BY StartTime, CourseName)
    FROM   
        A
)
SELECT B.* 
FROM B;

我得到这个结果:

ClassRoom CourseName StartTime EndTime Ranker
---------------------------------------------
1001      Course 1   0800   0900    0
1001      Course 1   0900   1000    0
1001      Course 1   1000   1100    0
1001      Course 1   1100   1200    0
1001      Course 2   1100   1200    1
1001      Course 2   1200   1300    1
1001      Course 1   1300   1400    2
1001      Course 1   1400   1500    2

请关注栏排名。如果我没有误解的话,在当前类(class)与之前类(class)不同的第一行,则 sum(1);接下来的行,其中当前类(class) == 上一类(class),然后求和(0),所以我对排名器的期望应该是:(0,0,0,0),(1,1),(1,1)但它给我 (0,0,0,0), (1,1), (2,2)。

为什么最后我得到 (2, 2) ?我错过了什么吗?

最佳答案

表达式:

CASE WHEN CourseName = PrevCourse THEN 0 ELSE 1 END

CourseNamePrevCourse 不同时返回 1

如果在 B 中再添加一列,您会看得更清楚:

B AS (
  SELECT ClassRoom
       , CourseName
       , StartTime
       , EndTime
       , CASE WHEN CourseName = PrevCourse THEN 0 ELSE 1 END flag -- check this
       , Ranker = SUM(CASE WHEN CourseName = PrevCourse THEN 0 ELSE 1 END)
                OVER (ORDER BY StartTime, CourseName)
  FROM   A
)

如果您想获得 (0,0,0,0), (1,1), (1,1) 形式的结果,您应该在 内添加一个 PARTITION BY 子句Ranker 列的 OVER:

Ranker = SUM(CASE WHEN CourseName = PrevCourse THEN 0 ELSE 1 END)
         OVER (PARTITION BY CourseName ORDER BY StartTime)

请参阅demo .

关于sql - SQL Server 中求和函数的工作方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72759288/

相关文章:

sql - 在子查询中使用声明的变量

sql-server - 使用 Profiler Trace 和应用程序名称列查找哪些应用程序访问我的服务器

asp.net - 使用 SQL Server 触发器更新插入时的旧行

MySQL 列的 SUM

mysql - sql中的求和语句

MySQL:累积字段中每个特定值的出现次数

sql - select count(1) 与 select rowcnt from sysindexes 性能和使用?

sql - SSMS QueryBuilder 可以在设计 View 中使用多个数据库吗?

php - 通知 : Array to string conversion with date

java - 使用java和mysql服务器的读/写模式