SQL Server 条件小计查询

Posted

技术标签:

【中文标题】SQL Server 条件小计查询【英文标题】:SQL Server conditional subtotal query 【发布时间】:2016-03-31 19:31:22 【问题描述】:

给定下表:

    create table #T
    (
    user_id int,
    project_id int,
    datum datetime,
    status varchar(10),
    KM int
    )

insert into #T values 
    (1, 1, '20160301 10:25', 'START', 1000), 
    (1, 1, '20160301 10:28', 'PASS', 1008), 
    (2, 2, '20160301 10:29', 'START', 2000),
    (1, 1, '20160301 11:08', 'STOP', 1045), 
    (3, 3, '20160301 10:25', 'START', 3000),
    (2, 2, '20160301 10:56', 'STOP', 2020), 
    (1, 4, '20160301 15:00', 'START', 1045), 
    (4, 5, '20160301 15:10', 'START', 400), 
    (1, 4, '20160301 15:10', 'PASS', 1060), 
    (1, 4, '20160301 15:20', 'PASS', 1080), 
    (1, 4, '20160301 15:30', 'STOP', 1080), 
    (4, 5, '20160301 15:40', 'STOP', 450),
    (3, 3, '20160301 16:25', 'STOP', 3200)

我必须对给定用户和项目的 START 和 STOP 状态之间的轨道长度求和 预期的结果是这样的:

    user_id     project_id  datum      TOTAL_KM
----------- ----------- ---------- -----------
1           1           2016-03-01 45
1           4           2016-03-01 35
2           2           2016-03-01 20
3           3           2016-03-01 200
4           5           2016-03-01 50

如何在不使用集群的情况下实现这一目标? 性能是个问题(我每个月有超过 100 万条记录,我们必须保留数据好几年)

说明: 我们可以忽略状态为“PASS”的记录。基本上,我们必须从给定用户和项目的 STOP 记录中减去 START 记录的 KM 值。 START 和 STOP 之间可能有数百条记录(如示例数据中所述) 日期应该是 START 日期(如果我们有超过午夜交货的情况)

我认为我应该有一个带有 OVER() 子句的 SELECT,但我不知道如何制定我的查询来尊重这些条件。

有什么想法吗?

【问题讨论】:

您使用的是什么版本的 SQL Server? 【参考方案1】:
SELECT  t.[user_id],
        t.project_id,
        cast(t.datum as date) as datum,
        t1.KM- t.KM as KM
FROM #T t
INNER JOIN #T t1 
    ON t.[user_id]=t1.[user_id] and t.project_id = t1.project_id 
WHERE t.[status] = 'START' and t1.[status] = 'STOP'
ORDER BY t.[user_id],
        t.project_id,
        cast(t.datum as date)

输出:

user_id     project_id  datum      KM
----------- ----------- ---------- -----------
1           1           2016-03-01 45
1           4           2016-03-01 35
2           2           2016-03-01 20
3           3           2016-03-01 200
4           5           2016-03-01 50

(5 row(s) affected)

【讨论】:

如果您只是在寻找已完成的行程,最好进行内部连接。【参考方案2】:

这可以通过简单的自连接来实现。

其中一个例子:(这可能不是确切的查询,而只是一个想法)

Select 
    a.user_id,
    a.project_id,
    b.datum as StartDate,
    a.KM-b.KM as TotalKM
From #T a
Where status = 'STOP'
Join 
(
    Select user_id, project_id, KM From #t Where 
    status = 'START'
) b ON b.user_id = a.user_id, b.project_id = a.project_id
#T b

【讨论】:

这不是任何数据库方言中的有效 SQL 查询。 :-( @Gabor 正如我已经说过的那样,这是一个概念性的想法,而不是你想要的确切工作结果,所以投入只是因为你期待准确的查询。

以上是关于SQL Server 条件小计查询的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server - 如何将带有组小计的列添加到查询结果中

形成详细信息和小计的 SQL 查询 (MySQL)

SQL如何查询总计和小计

Transact-SQL 查询小计列

向 Firebird SQL 查询中的列添加小计

like小计