如何使用 SQL Server 2012 窗口函数来完成我的查询?

Posted

技术标签:

【中文标题】如何使用 SQL Server 2012 窗口函数来完成我的查询?【英文标题】:How to use a SQL Server 2012 Window Function to accomplish my query? 【发布时间】:2014-09-17 20:46:03 【问题描述】:

假设我有一张维修票表,如下所示:

Group   Ticket  Status
----------------------------
00798   299696  Open
21851   574587  Complete
21851   574588  Pending
21852   574589  Office
21866   574613  Test
21869   574617  Shipping
21870   574618  Repair
21871   574620  Open
32102   369151  Repair
43316   393920  Office
60669   433162  Office
65850   445815  Open
65999   446267  Complete
66215   446841  Repair
77818   473653  Complete
79691   477963  Office
82277   483787  Pending
86283   493697  Complete
86283   493698  Complete

仅当组中的每张票都已完成时,我才尝试获取状态为已完成的所有票的列表。因此,从这个数据集中,我会得到这些票:

446267     
473653     
493697    
493698   

我不会得到 574587,因为在其组 (21851) 中还有另一张票 (574588) 设置为待处理,未完成。

我已尝试将 ROW_NUMBER() OVER (PARTITION BY GroupNumber, [Status] ORDER BY GroupNumber) 的变体作为子查询,但无法解决这个问题。也许它可以用 group by 和一个子查询来完成?谢谢。

【问题讨论】:

我认为你可以用 WHERE NOT EXISTS(...) 来做到这一点 【参考方案1】:

SQL 小提琴:http://sqlfiddle.com/#!6/62ecb/2

这些都应该工作:

--get every record
select * 
from RepairTickets a
--where the status is complete
where [status] = 'Complete'
--and the status matches every...
and [status] = all 
(
    --other record's status
    select [status]
    from RepairTickets b
    --in the same group 
    where b.[Group] = a.[Group]
)

--get all records
select * 
from RepairTickets a
--where the status is complete
where [status] = 'Complete'
--where there is not
and not exists
(
    --any record
    select top 1 1
    from RepairTickets b
    --in the same group
    where b.[Group] = a.[Group]
    --but with a different status
    and b.[Status] != a.[Status]
)

注意:在上述两种情况下,因为我们知道我们只是在寻找完整的记录,我们可以通过替换与内部查询相关的 a.[Status] 的一些引用来优化;但是上面的内容应该更容易修改,因为您只需要在一个地方声明您感兴趣的状态。

【讨论】:

谢谢,我不知道“全部”,这两个都很好。【参考方案2】:

你想多了。窗口函数并不适用于所有情况。您可以简单地计算每个组中的票数与已完成票数的对比:

WITH tmp AS
(
    SELECT  GroupID,
            COUNT(TicketID) AS TotalTicket,
            SUM(CASE WHEN Status = 'Complete' THEN 1 ELSE 0 END) AS CompletedTicket
    FROM    Repair
    GROUP BY GroupID
)

SELECT      Repair.TicketID
FROM        tmp
INNER JOIN  Repair  ON tmp.GroupID = Repair.GroupID
WHERE       tmp.CompletedTicket = tmp.TotalTicket

(SQL Fiddle 目前已关闭,因此无法发布)

【讨论】:

以上是关于如何使用 SQL Server 2012 窗口函数来完成我的查询?的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server 2012 Windowing 函数计算运行总计

当列值更改时,如何将组号添加到 SQL Server 2012 中的顺序记录?

如何在 SQL Server 中使用带有框架的窗口函数执行 COUNT(DISTINCT)

如何在 SQL Server 2012 中使用 TRUNC 函数,因为我得到 'TRUNC' 不是一个公认的内置函数名称。'?

SQL Server SUM IF 使用具有多个条件的窗口函数

如何安装sqlserver2012