如何根据特殊条件选择数据?

时间:2015-12-03 10:53:13

标签: sql sql-server tsql

我说TABLE Audit COLUMN ID, STATUS, TIME,示例数据如下:

1. {ID = 1, STATUS = 'APPROVE', TIME = '2015-02-01'}
2. {ID = 1, STATUS = 'DECLINE', TIME = '2014-12-01'}
3. {ID = 1, STATUS = 'CLOSED', TIME = '2015-11-01'}
4. {ID = 2, STATUS = 'APPROVE', TIME = '2015-02-01'}
5. {ID = 3, STATUS = 'DECLINE', TIME = '2015-10-01'}
6. {ID = 4, STATUS = 'CLOSED', TIME = '2015-02-01'}

有一个条件:如果status='approve'然后忽略status='decline',则选择所有内容。

我是否知道如何构建查询以便只获取记录:1,3,4,5,6?

我目前的方式是首先使用status='approve' and 'closed'检索所有数据并将其存储到temptable,然后将status = 'decline' and ID not in @temptable的数据存储到@temptable。然后最终select * from @temptable

我想知道是否还有其他方法来处理这种情况?

3 个答案:

答案 0 :(得分:4)

您可以使用窗口函数:

WITH cte AS
(
SELECT *
 ,[dec] = COUNT(CASE WHEN STATUS = 'DECLINE' THEN 1 END) OVER (PARTITION BY ID)
 ,[app] = COUNT(CASE WHEN STATUS = 'APPROVE' THEN 1 END) OVER (PARTITION BY ID)
FROM #Audit
)
SELECT ID, STATUS, [TIME]
FROM cte
WHERE NOT ([dec] >= 1 AND [app] >= 1 AND [STATUS] = 'DECLINE');

LiveDemo

您的专栏TIME可能会产生误导,尤其是当它只保留日期时:)

答案 1 :(得分:2)

这个想法是要获得所有已经批准的,并且那些跳过被拒绝的那些。 我现在无法尝试,但它应该有效:

;WITH App (ID, app) AS
    (SELECT ID, COUNT(1) FROM #Audit WHERE STATUS = 'APPROVE' GROUP BY ID UNION
    SELECT ID, 0 FROM #Audit WHERE ID NOT IN (SELECT ID FROM #Audit WHERE STATUS = 'APPROVE')  GROUP BY ID )
SELECT *, ISNULL(App.app, 0) 
FROM #Audit LEFT OUTER JOIN App ON #Audit.ID = App.ID
WHERE ISNULL(App.app, 0) = 0 OR (App.app = 1 AND #audit.status != 'DECLINE')

答案 2 :(得分:1)

select *
from audit a1
where not exists(
    select * from audit a2 
    where a2.status='approve' and a1.status='decline' and a2.id=a1.id
)