【问题标题】:Reducing Output from two UNION queries, too many resulting rows currently减少两个 UNION 查询的输出,当前结果行太多
【发布时间】:2016-12-14 05:16:58
【问题描述】:

SQL Server:这是我的基本查询。我不知道如何正确地使这个“结果”在每个商店/日期只显示一行,这两个查询分别填写第 3 和第 4 列。现在结果是每个商店/日期给我 2 行,其中 NULL对立的列。每个商店/日期应该只有一行,第三列偶尔会出现 NULL。

DECLARE @START DATETIME, @END DATETIME
SET @END   = CAST(CAST(GETDATE() AS DATE) AS DATETIME) + '03:00'
SET @START = @END - 7

SELECT 
    @START [From], @END [To]

SELECT 
    DivisionName, DateClosed, COUNT(OrderId) AS PREDATED, NULL AS DAYOF 
FROM 
    (SELECT 
         o.OrderId, DivisionName, DateCreated, 
         CONVERT(Date, DateClosed) [DateClosed]   
     FROM 
         POS.Orders o WITH(NOLOCK)
     JOIN 
         POS.OrderDetails od WITH(NOLOCK) ON o.OrderId = od.OrderId
     JOIN 
         Directory.Divisions d WITH(NOLOCK) ON o.DivisionId = d.DivisionId
     WHERE 
         DateClosed BETWEEN @START AND @END AND DateCreated < @START) t
 GROUP BY 
     DivisionName, DateClosed

 UNION

 SELECT 
     DivisionName, DateClosed, NULL AS PREDATED, COUNT(OrderID) AS DAYOF
 FROM 
     (SELECT 
          o.OrderId, DivisionName, DateCreated, 
          CONVERT(Date,DateClosed)[DateClosed]
      FROM 
          POS.Orders o WITH(NOLOCK)
      JOIN 
          POS.OrderDetails od WITH(NOLOCK) ON o.OrderId = od.OrderId
      JOIN 
          Directory.Divisions d WITH(NOLOCK) ON o.DivisionId = d.DivisionId
      WHERE 
          DateClosed BETWEEN @START AND @END AND DateCreated >= @START) s
GROUP BY 
    DivisionName, DateClosed

【问题讨论】:

  • 只需使用;WITH t as (&lt;your query&gt;) SELECT DivisionName, DateClosed, MAX(PREDATED) AS PREDATED, MAX(DAYOF) AS DAYOF FROM t GROUP BY DivisionName, DateClosed; ;)。
  • 您可以通过仅选择完整日期范围的数据集一次来简化查询,然后在COUNT 中使用 case 语句来选择您想要的日期范围算数。当你重复这样的代码时,通常会有更好的方法来做到这一点。如果您有兴趣,我会发布更多详细信息
  • shA.t - 上面的 ;with t 建议效果很好。现在我需要阅读并理解为什么,以便我在未来能够熟练地复制这种技术。如果您将此添加为答案,我将向上投票。

标签: sql-server merge union


【解决方案1】:

你可以使用这样的结构:

;WITH t as (
    <your query>
) 
SELECT DivisionName, DateClosed, MAX(PREDATED) AS PREDATED, MAX(DAYOF) AS DAYOF 
FROM t 
GROUP BY DivisionName, DateClosed;

我没有你的示例数据,但你可以使用这样的查询:

SELECT 
     DivisionName, CONVERT(Date, DateClosed) [DateClosed],
     COUNT(CASE WHEN DateClosed BETWEEN @START AND @END AND DateCreated < @START THEN 0 END) AS PREDATED,
     COUNT(CASE WHEN DateClosed BETWEEN @START AND @END AND DateCreated >= @START THEN 0 END) AS DAYOF
 FROM 
     POS.Orders o WITH(NOLOCK)
 JOIN 
     POS.OrderDetails od WITH(NOLOCK) ON o.OrderId = od.OrderId
 JOIN 
     Directory.Divisions d WITH(NOLOCK) ON o.DivisionId = d.DivisionId
 GROUP BY 
     DivisionName, DateClosed

【讨论】:

  • 这看起来非常有希望,但由于 BETWEEN 内容无法排除范围之外的订单,因此导致了成千上万的单独行。
  • 我尝试将 WHERE DateClosed BETWEEN .... 移到 GROUP BY 之前更下方,这有效,但这导致了 12000 行正确的个人结果,比我开始时更糟,试图让我的两个原始 SUM 结果进一步合并。
  • 为什么您认为第二种解决方案更糟糕?由于性能问题,第二个更好!?还有可读性问题!?
  • 是的,第二个在视觉和逻辑上看起来都很棒。但结果是同一日期范围的 12000 行。第一个使用我的原始查询和分号语法将我的 160 个交错行减少到 92 个合并行,完美。 link
猜你喜欢
  • 1970-01-01
  • 2019-11-20
  • 1970-01-01
  • 2019-11-07
  • 2017-04-05
  • 1970-01-01
  • 2015-05-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多