3

我想在一行中查找根据多个列的属性聚合的数据。这可能听起来像是一堆乱码,所以我给你举个例子……这是一个包含三列的数据库表:

GroupingId     Type           Date
1              NULL           1/1/11
1              NULL           2/2/22
2              NULL           1/1/11
2              A              2/2/22
3              A              1/1/11
3              B              2/2/22
4              A              1/1/11
4              NULL           2/2/22

我想做一个 SELECT,然后按 GroupingId 分组。这很容易。

但是对于其他两列,我想要一些真正依赖于这两列的东西。如果我只想要任何给定组的 MAX 日期,那将很简单。我真正想要的是 Type 更喜欢 NOT NULL,而 Date 应该是 MAX ......但我希望它们总是来自同一行(Type 值是 NOT NULL 优先)。

所以我的结果应该是这样的

1       NULL      2/2/22       // both Types are null, so last date chosen
2       A         2/2/22       // one Type not null, so that date chosen
3       B         2/2/22       // both Types not null, so last date chosen
4       A         1/1/11       // one Type not null, so that date chosen (and it is not the most recent date)

如果我在 Date 上做一个 MAX,那是不对的。如果我对 Type 执行 COALESCE,我将在 NULL 上得到一个非空值……但不一定是最近的。

有没有一种干净的方法可以做到这一点?我想我知道如何使用系列选择、表变量和 UNION 来做到这一点,这就是我将尝试前进的方式,但如果有一个干净的 SQL 解决方案,有人甚至可以点头,那将是受欢迎的。

我在 SQL Server 中,但我猜如果有一种干净的 SQL 方法可以做到这一点,它可能与数据库无关。

4

2 回答 2

2

像这样?

;WITH CTESample (GroupingId, Type, Date) AS
(
    SELECT 1, NULL, '1/1/11'    UNION ALL
    SELECT 1, NULL, '2/2/22'    UNION ALL
    SELECT 2, NULL, '1/1/11'    UNION ALL
    SELECT 2, 'A', '2/2/22'     UNION ALL
    SELECT 3, 'A', '1/1/11'     UNION ALL
    SELECT 3, 'B', '2/2/22'     UNION ALL
    SELECT 4, 'A', '1/1/11'     UNION ALL
    SELECT 4, NULL, '2/2/22'    
)
,Partitioned AS
(
    SELECT *
            ,rNum = ROW_NUMBER() OVER (PARTITION BY GroupingID ORDER BY Type DESC, Date DESC)
    FROM CTESample
)
SELECT *
FROM Partitioned
WHERE rNum = 1
于 2013-01-09T21:00:41.597 回答
1

这是使用Rank().

所以,我实在是太慢了……别告诉我的老板。

无论如何,一个例子:

SELECT
  [sub].[GroupingID],
  [sub].[Type],
  [sub].[Date]
FROM
(
  SELECT 
    [GroupingID],
    [Type],
    [Date],
    Rank() OVER(PARTITION BY [GroupingID] ORDER BY (CASE WHEN [Type] IS NULL THEN 0 ELSE 1 END) DESC, [Date] DESC, [Type] ASC) AS [Rank]
  FROM [Data]
) AS [sub]
WHERE [sub].[Rank] = 1
ORDER BY [GroupingID] ASC
于 2013-01-09T20:46:51.087 回答