在仍按MIN聚合排序的同时返回所有列

时间:2014-05-21 16:15:54

标签: sql-server tsql

首先让我说我不是数据库人,而且我完全不知道自己在做什么。即使与问题没有直接关系,我也欢迎任何改进的意见或建议。

无论如何,我有两个表,事件和事件。非常典型的设置:Occurrences具有Events.Id的外键,创建一对多的关系。出现时有一个StartDate和EndDate(尽管名称都是完整的日期时间值)。所以我想要做的是为所有事件选择所有列,其中Occurrences中至少有一个相关行,其中StartDate的未来值(尚未启动)或EndDate的未来值(已启动,但尚未结束)

我从以下内容中得到了以下查询(这里有一些逻辑用于获取“实时”事件,已发布但未过期等等。非常直接的内容):

DECLARE @PublishedStatus INT = 2
SELECT *
FROM [dbo].[Events] e
INNER JOIN [dbo].[Occurrences] o
ON e.Id = o.EventId
    AND (o.StartDate > GETUTCDATE() OR o.EndDate > GETUTCDATE())
WHERE e.Status = @PublishedStatus
    AND e.PublishDate IS NOT NULL
    AND e.PublishDate <= GETUTCDATE()
    AND (e.ExpireDate IS NULL OR e.ExpireDate > GETUTCDATE())

问题是我现在想要通过选定的Occurrences行中的最小StartDate值来排序。如果我尝试添加:

ORDER BY MIN(o.StartDate)

如果不添加:

,它将无效
GROUP BY e.Id

然后当然需要将我的选择更改为

SELECT e.Id

现在,问题是我需要来自Events的所有列,而不仅仅是Id。我知道这是GROUP BY的工作方式,所以这并不奇怪。我只是想找到一个中间地带,我可以在某种程度上同时做两件事。不幸的是,正如我在开始时说的那样,我不是这方面的专家,而且我已经达到了目前能力的极限。

此外,对于它的价值,这将是存储过程的基础。它进入了一个ORM,所以我需要返回所有列来正确实例化代表该表的类。我不希望显式指定所有列名,因为我需要始终将此存储过程与对表的模式所做的任何更新同步,如果有任何更新(添加其他列等),但是这是达到我需要的唯一方式,我会处理。

2 个答案:

答案 0 :(得分:1)

如果我理解正确(我不确定)你可以尝试这样的事情

DECLARE @PublishedStatus INT = 2

SELECT e.*
  FROM
(
    SELECT e.Id, MIN(o.StartDate) MinStartDate
      FROM [dbo].[Events] e INNER JOIN [dbo].[Occurrences] o
        ON e.Id = o.EventId
       AND (o.StartDate > GETUTCDATE() OR o.EndDate > GETUTCDATE())
     WHERE e.Status = @PublishedStatus
       AND e.PublishDate IS NOT NULL
       AND e.PublishDate <= GETUTCDATE()
       AND (e.ExpireDate IS NULL OR e.ExpireDate > GETUTCDATE())
      GROUP BY e.Id
 ) q JOIN [dbo].[Events] e 
   ON q.Id = e.Id
 ORDER BY MinStartDate

答案 1 :(得分:1)

ORDER BY MIN(o.StartDate)表示您想按升序订购StartDate。对吗? 因此,在这种情况下,您只需添加Order By StartDate,如: -

DECLARE @PublishedStatus INT = 2
SELECT *
FROM [dbo].[Events] e
INNER JOIN [dbo].[Occurrences] o
 ON e.Id = o.EventId
AND (o.StartDate > GETUTCDATE() OR o.EndDate > GETUTCDATE())
WHERE e.Status = @PublishedStatus
AND e.PublishDate IS NOT NULL
AND e.PublishDate <= GETUTCDATE()
AND (e.ExpireDate IS NULL OR e.ExpireDate > GETUTCDATE())
Order By o.StartDate ASC