2014-10-02 92 views
0

这是一个SQL查询,我很快写了一个关于每个月PayPal购买数量的报告,数据库是基于已导入数据的我自己的构建。根据月份重复JOIN

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 ...)代码?

谢谢!

+1

我认为你需要一个'PIVOT'。首先使用ItemTitle,Month,Count进行表格查询。之后,尝试“枢轴”或使用类似的技术。像[this](http://sqlhints.com/2014/03/10/pivot-and-unpivot-in-sql-server/)。 – 2014-10-02 20:58:40

回答

0

你的意思是像一个PIVOT

你可以PIVOT上DATEPART(月,DateTimeUtc)...

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 
0

通过网络和年月过滤到一个临时表@var然后转动到您的最终选择次数群。 你可以试试吗?如果你需要,我可以在这里创建一个迷你分贝来帮助你。

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; 
3

我还没有真正写的前一个支点,但在理论上它看起来像这样:

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)方法将其归结为单个连接。单加盟仍然是必要的,以避免空值/在结果中丢失物品,也可能是通过增加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 

目前仍然在这里一些重复的代码,但我认为你会同意这是一个巨大的改善比原来...我有更多的信心,这将实际上工作;)

+0

整洁的方式处理月份的替代版本! – 2014-10-02 21:27:04

+0

对于数据透视,聚合需要针对特定​​的列,例如count(mth),而IN子句的值需要使用[1],[2]等括号,因为标识符无法启动与一个数字。 – jpw 2014-10-02 21:39:48

+1

你应该更多地写PIVOTs他们很有趣。 – Taryn 2014-10-02 21:44:17