0

我将获得一些需要根据某些条件过滤掉的数据。样本数据:

Cust_ID Date    Result
1   2013-08-15  On hold
2   2013-08-16  NULL
3   2013-08-18  WIP
1   2013-08-20  Completed
3   2013-08-25  NULL
4   2013-08-28  NULL
4   2013-08-29  NULL

条件:

  1. 根据最新日期获取不同的 Cust_ID。(即 Max(Date))
  2. 如果最新日期的结果为空,则使用除 NULL 之外的任何其他结果获取最新记录。
  3. 如果所有具有相同 Cust_ID 的记录的 Result 为 NULL,则根据 Date 选择最新的记录

所需的输出应该是:

Cust_ID Date    Result
1   2013-08-20  Completed
2   2013-08-16  NULL    
3   2013-08-18  WIP
4   2013-08-29  NULL

请指教。

4

2 回答 2

0

首先,您需要IS NULL在每一行上设置一个指标:

SQL小提琴

MS SQL Server 2008 架构设置

CREATE TABLE dbo.Results
    ([CustID] int, [Date] datetime, [Result] varchar(9))
GO

INSERT INTO dbo.Results
    ([CustID], [Date], [Result])
VALUES
    (1, '2013-08-15 00:00:00', 'On Hold'),
    (2, '2013-08-16 00:00:00', NULL),
    (3, '2013-08-18 00:00:00', 'WIP'),
    (1, '2013-08-20 00:00:00', 'Completed'),
    (3, '2013-08-25 00:00:00', NULL),
    (4, '2013-08-28 00:00:00', NULL),
    (4, '2013-08-29 00:00:00', NULL)
GO

查询 1

SELECT *,CASE WHEN Result IS NULL THEN 0 ELSE 1 END IsNotNull
  FROM dbo.Results

结果

| CUSTID |                          DATE |    RESULT | ISNOTNULL |
|--------|-------------------------------|-----------|-----------|
|      1 | August, 15 2013 00:00:00+0000 |   On Hold |         1 |
|      2 | August, 16 2013 00:00:00+0000 |    (null) |         0 |
|      3 | August, 18 2013 00:00:00+0000 |       WIP |         1 |
|      1 | August, 20 2013 00:00:00+0000 | Completed |         1 |
|      3 | August, 25 2013 00:00:00+0000 |    (null) |         0 |
|      4 | August, 28 2013 00:00:00+0000 |    (null) |         0 |
|      4 | August, 29 2013 00:00:00+0000 |    (null) |         0 |

然后您需要确定每个客户的第一NULL行和第一NOT NULL行。您可以使用该ROW_NUMBER()功能。您还需要知道每个客户是否有任何NOT NULL行:

查询 2

SELECT *,
       ROW_NUMBER()OVER(PARTITION BY CustID,IsNotNull ORDER BY [Date] DESC) _rn,
       COUNT(Result)OVER(PARTITION BY CustID) NotNullCount
  FROM(
    SELECT *,CASE WHEN Result IS NULL THEN 0 ELSE 1 END IsNotNull
    FROM dbo.Results
  )X1

结果

| CUSTID |                          DATE |    RESULT | ISNOTNULL | _RN | NOTNULLCOUNT |
|--------|-------------------------------|-----------|-----------|-----|--------------|
|      1 | August, 20 2013 00:00:00+0000 | Completed |         1 |   1 |            2 |
|      1 | August, 15 2013 00:00:00+0000 |   On Hold |         1 |   2 |            2 |
|      2 | August, 16 2013 00:00:00+0000 |    (null) |         0 |   1 |            0 |
|      3 | August, 25 2013 00:00:00+0000 |    (null) |         0 |   1 |            1 |
|      3 | August, 18 2013 00:00:00+0000 |       WIP |         1 |   1 |            1 |
|      4 | August, 29 2013 00:00:00+0000 |    (null) |         0 |   1 |            0 |
|      4 | August, 28 2013 00:00:00+0000 |    (null) |         0 |   2 |            0 |

最后,您可以使用计算的行号过滤掉第一NOT NULL行(如果有)或第一NULL行(如果没有行):NOT NULL

查询 3

SELECT CustID,[Date],Result
FROM(
  SELECT *,
         ROW_NUMBER()OVER(PARTITION BY CustID,IsNotNull ORDER BY [Date] DESC) _rn,
         COUNT(Result)OVER(PARTITION BY CustID) NotNullCount
    FROM(
      SELECT *,CASE WHEN Result IS NULL THEN 0 ELSE 1 END IsNotNull
      FROM dbo.Results
    )X1
  )X2
 WHERE _rn = 1 AND SIGN(NotNullCount) = IsNotNull

结果

| CUSTID |                          DATE |    RESULT |
|--------|-------------------------------|-----------|
|      1 | August, 20 2013 00:00:00+0000 | Completed |
|      2 | August, 16 2013 00:00:00+0000 |    (null) |
|      3 | August, 18 2013 00:00:00+0000 |       WIP |
|      4 | August, 29 2013 00:00:00+0000 |    (null) |
于 2013-10-09T01:47:41.967 回答
0

您可以使用 CTE 轻松完成,请注意 CTE 不是“需要的”(您可以使用子查询),但我认为它可以清楚地说明您在做什么。

WITH NonNull AS
(
   SELECT CustID, MAX(Date) as Date
   FROM tablename
   GROUP BY CustID
   WHERE Result is not null
), Others AS
(
   SELECT CustID, MAX(Date) as Date
   FROM tablename
   GROUP BY CustID
   WHERE CustID NOT IN (SELECT CustID FROM NonNull)
), AlltogetherNow -- not really needed but clearer
(
   SELECT CustID, Date
   FROM NonNull
   UNION ALL
   SELECT CustID, Date
   FROM Others
)
SELECT A.CustID, A.Date, J.Results
FROM AlltogetherNow A
JOIN tablename J ON A.CustID = J.CustID AND A.Date = J.Date
于 2013-10-09T01:33:18.023 回答