根据月份重复加入

时间:2014-10-02 20:53:22

标签: sql-server

这是一个我快速编写的SQL查询,以便为我提供每个月PayPal购买数量的报告,该数据库是我自己构建的,基于已导入的数据。

SELECT
    Items.ItemTitle,
    February.Cnt As February,
    March.Cnt As March,
    April.Cnt As April,
    May.Cnt As May,
    June.Cnt As June,
    July.Cnt As July,
    August.Cnt As August,
    September.Cnt As September
FROM

( SELECT DISTINCT ItemTitle FROM PayPalHistory ) As Items

LEFT OUTER JOIN

( SELECT ItemTitle, COUNT(*) As Cnt FROM PayPalHistory WHERE
    DateTimeUtc >= '2014-02-01' AND DateTimeUtc < '2014-03-01' AND Net > 0.00
GROUP BY ItemTitle ) AS February

ON Items.ItemTitle = February.ItemTitle

LEFT OUTER JOIN

( SELECT ItemTitle, COUNT(*) As Cnt FROM PayPalHistory WHERE
    DateTimeUtc >= '2014-03-01' AND DateTimeUtc < '2014-04-01' AND Net > 0.00
GROUP BY ItemTitle ) AS March

ON Items.ItemTitle = March.ItemTitle

LEFT OUTER JOIN

( SELECT ItemTitle, COUNT(*) As Cnt FROM PayPalHistory WHERE
    DateTimeUtc >= '2014-04-01' AND DateTimeUtc < '2014-05-01' AND Net > 0.00
GROUP BY ItemTitle ) AS April

ON Items.ItemTitle = April.ItemTitle

LEFT OUTER JOIN

( SELECT ItemTitle, COUNT(*) As Cnt FROM PayPalHistory WHERE
    DateTimeUtc >= '2014-05-01' AND DateTimeUtc < '2014-06-01' AND Net > 0.00
GROUP BY ItemTitle ) AS May

ON Items.ItemTitle = May.ItemTitle

LEFT OUTER JOIN

( SELECT ItemTitle, COUNT(*) As Cnt FROM PayPalHistory WHERE
    DateTimeUtc >= '2014-06-01' AND DateTimeUtc < '2014-07-01' AND Net > 0.00
GROUP BY ItemTitle ) AS June

ON Items.ItemTitle = June.ItemTitle

LEFT OUTER JOIN

( SELECT ItemTitle, COUNT(*) As Cnt FROM PayPalHistory WHERE
    DateTimeUtc >= '2014-07-01' AND DateTimeUtc < '2014-08-01' AND Net > 0.00
GROUP BY ItemTitle ) AS July

ON Items.ItemTitle = July.ItemTitle

LEFT OUTER JOIN

( SELECT ItemTitle, COUNT(*) As Cnt FROM PayPalHistory WHERE
    DateTimeUtc >= '2014-08-01' AND DateTimeUtc < '2014-09-01' AND Net > 0.00
GROUP BY ItemTitle ) AS August

ON Items.ItemTitle = August.ItemTitle

LEFT OUTER JOIN

( SELECT ItemTitle, COUNT(*) As Cnt FROM PayPalHistory WHERE
    DateTimeUtc >= '2014-09-01' AND DateTimeUtc < '2014-10-01' AND Net > 0.00
GROUP BY ItemTitle ) AS September

ON Items.ItemTitle = September.ItemTitle

ORDER BY
    ItemTitle ASC

你在这里看到一种模式吗? :)

有没有办法可以使用循环或其他构造来消除重复LEFT OUTER JOIN ( SELECT ... )代码?

谢谢!

5 个答案:

答案 0 :(得分:3)

我之前没有真正写过PIVOT,但理论上它看起来像这样:

SELECT ItemTitle, [1] AS January, [2] AS February, [3] AS March, [4] AS April, [5] AS May
      , [6] AS June, [7] AS July, [8] AS August, [9] AS September, [10] AS October 
      [11] AS November, [12] AS December
FROM 
(
   SELECT ItemTitle, Month(DateTimeUtc) AS [Month]
   FROM PayPalHistory 
   WHERE DateTimeUtc >= '2014-01-01' AND DateTimeUtc < '2015-01-01' AND Net > 0.00
) p
PIVOT
( 
   COUNT ([Month]) FOR [Month] IN ([1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12] )
) AS pvt;

我不太确定我是否正确处理月份列名,或者Sql Server如何在此处将此整数作为列名处理,或者如何处理*而不是聚合函数中的列名称。您可能需要将月份编号投影到字符串,作为嵌套在FROM子句中的查询的一部分,以使其工作。它肯定需要一些调整,但如果我有你的真实数据,它不会花太多工作。

或者,您可以使用嵌套的GROUP BY和SUM(CASE)方法将其转换为单个连接。单个连接仍然是必要的,以避免结果中的NULL /缺少项目,也可以通过向每个月列添加COALESCE()函数来避免:

SELECT b.ItemTitle,
   SUM(CASE WHEN [Month] = 1  THEN Cnt ELSE 0 END) As January,
   SUM(CASE WHEN [Month] = 2  THEN Cnt ELSE 0 END) As February,
   SUM(CASE WHEN [Month] = 3  THEN Cnt ELSE 0 END) As March,
   SUM(CASE WHEN [Month] = 4  THEN Cnt ELSE 0 END) As April,
   SUM(CASE WHEN [Month] = 5  THEN Cnt ELSE 0 END) As May,
   SUM(CASE WHEN [Month] = 6  THEN Cnt ELSE 0 END) As June,
   SUM(CASE WHEN [Month] = 7  THEN Cnt ELSE 0 END) As July,
   SUM(CASE WHEN [Month] = 8  THEN Cnt ELSE 0 END) As August,
   SUM(CASE WHEN [Month] = 9  THEN Cnt ELSE 0 END) As September,
   SUM(CASE WHEN [Month] = 10 THEN Cnt ELSE 0 END) As October,
   SUM(CASE WHEN [Month] = 11 THEN Cnt ELSE 0 END) As November,
   SUM(CASE WHEN [Month] = 12 THEN Cnt ELSE 0 END) As December 
FROM (SELECT DISTINCT ItemTitle FROM PayPalHistory) b
LEFT JOIN (
      SELECT ItemTitle, COUNT(*) As Cnt, MONTH(DatetimeUtc) As [Month]
      FROM PayPalHistory 
      WHERE DateTimeUtc >= '2014-01-01' AND DateTimeUtc < '2015-01-01' AND Net > 0.00
      GROUP BY ItemTitle, MONTH(DateTimeUtc)
   ) m on m.ItemTitle = b.ItemTitle
GROUP BY b.ItemTitle

这里仍然有一些重复的代码,但我认为你会同意它比原来的巨大的改进...我还有很多信心这实际上会起作用;)

答案 1 :(得分:2)

此PIVOT查询可能是您想要的,请试一试:

SELECT 
    ItemTitle, 
    [January],  [February], [March],   [April], 
    [May],      [June],     [July],    [August], 
    [September],[October],  [November],[December]
FROM 
  (
  SELECT ItemTitle, DATENAME(MONTH, DateTimeUtc) Month
  FROM paypalhistory 
  WHERE Net > 0.0 AND DateTimeUtc >= '2014-01-01' AND DateTimeUtc < '2015-01-01'
  ) AS p
  PIVOT ( COUNT (Month) FOR Month IN
    ( [January], [February], [March], [April], [May], [June], 
      [July], [August], [September],[October], [November], [December] )
  ) AS pvt
ORDER BY ItemTitle;

答案 2 :(得分:0)

你的意思是PIVOT

你可以在DATEPART(月,DateTimeUtc)上潜伏......

答案 3 :(得分:0)

SELECT
    ItemTitle
    , SUM( CASE WHEN DateTimeUtc >= '2014-01-01' AND DateTimeUtc < '2014-02-01' AND Net > 0.00 THEN 1 ELSE 0 END ) As January
    , SUM( CASE WHEN DateTimeUtc >= '2014-02-01' AND DateTimeUtc < '2014-03-01' AND Net > 0.00 THEN 1 ELSE 0 END ) As February
    , SUM( CASE WHEN DateTimeUtc >= '2014-03-01' AND DateTimeUtc < '2014-04-01' AND Net > 0.00 THEN 1 ELSE 0 END ) As March
    , SUM( CASE WHEN DateTimeUtc >= '2014-04-01' AND DateTimeUtc < '2014-05-01' AND Net > 0.00 THEN 1 ELSE 0 END ) As April
    , SUM( CASE WHEN DateTimeUtc >= '2014-05-01' AND DateTimeUtc < '2014-06-01' AND Net > 0.00 THEN 1 ELSE 0 END ) As May
    , SUM( CASE WHEN DateTimeUtc >= '2014-06-01' AND DateTimeUtc < '2014-07-01' AND Net > 0.00 THEN 1 ELSE 0 END ) As June
    , SUM( CASE WHEN DateTimeUtc >= '2014-07-01' AND DateTimeUtc < '2014-08-01' AND Net > 0.00 THEN 1 ELSE 0 END ) As July
    , SUM( CASE WHEN DateTimeUtc >= '2014-08-01' AND DateTimeUtc < '2014-09-01' AND Net > 0.00 THEN 1 ELSE 0 END ) As August
    , SUM( CASE WHEN DateTimeUtc >= '2014-09-01' AND DateTimeUtc < '2014-10-01' AND Net > 0.00 THEN 1 ELSE 0 END ) As September
    , SUM( CASE WHEN DateTimeUtc >= '2014-10-01' AND DateTimeUtc < '2014-11-01' AND Net > 0.00 THEN 1 ELSE 0 END ) As October
    , SUM( CASE WHEN DateTimeUtc >= '2014-11-01' AND DateTimeUtc < '2014-12-01' AND Net > 0.00 THEN 1 ELSE 0 END ) As November
    , SUM( CASE WHEN DateTimeUtc >= '2014-12-01' AND DateTimeUtc < '2015-01-01' AND Net > 0.00 THEN 1 ELSE 0 END ) As December
FROM PayPalHistory
GROUP BY ItemTitle

答案 4 :(得分:0)

按月计算的计数组按年份过滤到临时@var表,然后转到最终选择。 你能试试吗?如果需要,我可以在这里创建一个迷你数据库来帮助你。