我想知道如果它们中的任何一个具有某个标志值,如何排除某个值的所有数据点。 (我在这个问题的底部提供了查询)
例子。 这是我表中的当前数据(该标志可以采用超过2个值(N,P和A))
RevisionID DateTime Value Flag
21026 2017-01-01 06:00:00.000 224.4 N
21026 2017-01-01 07:00:00.000 476.8 P
21026 2017-01-01 08:00:00.000 588.6 N
21027 2017-01-01 07:00:00.000 138.4 N
21027 2017-01-01 08:00:00.000 683.6 N
上面的数据将按照给定日期时间的最高修订版进行展平(我已经可以使用提供的查询执行此操作)。
结果将如下所示
RevisionID DateTime Value Flag
21026 2017-01-01 06:00:00.000 224.4 N
21027 2017-01-01 07:00:00.000 138.4 N
21027 2017-01-01 08:00:00.000 683.6 N
但我想要做的是,如果任何有标志P的数据点,不应显示所有相关的日期时间
目前第2行包含P标志
21026 2017-01-01 07:00:00.000 476.8 P
我希望最终结果看起来像这样
RevisionID DateTime Value Flag
21026 2017-01-01 06:00:00.000 224.4 N
21027 2017-01-01 08:00:00.000 683.6 N
下面提供的查询将使数据变平,现在我想排除所有数据点,即使其中一个被标记为P
CREATE TABLE #data ( RevisionID INT, _datetime DATETIME, _value FLOAT, flag CHAR)
INSERT INTO #data VALUES
(21026,'2017-01-01 06:00:00.000',224.4,'N'),
(21026,'2017-01-01 07:00:00.000',476.8,'P'),
(21026,'2017-01-01 08:00:00.000',588.6,'N'),
(21027,'2017-01-01 07:00:00.000',138.4,'N'),
(21027,'2017-01-01 08:00:00.000',683.6,'N')
WITH RNData AS
(
SELECT d.RevisionID, d._datetime, d._value, d.flag, ROW_NUMBER()
OVER (PARTITION BY d._datetime ORDER BY d._datetime, d.RevisionID DESC) AS rn
FROM #data d
)select * from RNData where rn = 1
答案 0 :(得分:3)
您也可以使用窗口函数:
WITH d AS (
SELECT d.RevisionID, d._datetime, d._value, d.flag,
ROW_NUMBER() OVER (PARTITION BY d._datetime ORDER BY d.RevisionID DESC) AS seqnum,
SUM(CASE WHEN d.flag = 'P' THEN 1 ELSE 0 END) OVER (PARTITION BY d._datetime) as cnt_P
FROM #data d
)
SELECT d.*
FROM d
WHERE seqnum = 1 AND cnt_P = 0;
请注意,您不应重复ORDER BY
。
如果该标记仅采用'N'
和'P'
的值,那么您可以使用一个小的快捷方式:
WITH d AS (
SELECT d.RevisionID, d._datetime, d._value, d.flag,
ROW_NUMBER() OVER (PARTITION BY d._datetime ORDER BY d.RevisionID DESC) AS seqnum,
MAX(d.flag) OVER (PARTITION BY d._datetime) as max_flag
FROM #data d
)
SELECT d.*
FROM d
WHERE seqnum = 1 AND max_flag = 'P';
答案 1 :(得分:0)
使用CASE表达式(条件聚合):
WITH RNData AS
(
SELECT
d.RevisionID, d._datetime, d._value, d.flag,
ROW_NUMBER() OVER (PARTITION BY d._datetime ORDER BY d._datetime, d.RevisionID DESC) AS rn,
MAX(CASE WHEN flag = 'P' THEN 1 ELSE 0 END) OVER (PARTITION BY d._datetime) AS flagged_p
FROM #data d
)
select *
from RNData
where rn = 1
and flagged_p = 0;
答案 2 :(得分:0)
另一种方法
select *
from
( SELECT d.RevisionID, d._datetime, d._value, d.flag
, ROW_NUMBER() OVER (PARTITION BY d._datetime ORDER BY d.RevisionID DESC) AS rn
FROM #data d
WHERE NOT EXISTS (SELECT 1 FROM #data p WHERE d._datetime = p._datetime and p.flag = 'P')
AND d.flag <> 'P'
) tt
where tt.rn = 1
AND d.flag <> 'P'
不是必需的,但可能会提高效率