2013-04-23 120 views
2

我找不到任何问题/答案,可以帮助我接近我的目标。我有以下表格check code on SQL Fiddle如何按行和列进行分组?

SITENAME RTYPE SEASON CTRSTAT CTRTYPE UNITS STARTDATE WKTYPE INVSTAT 
site1 T2B P  null  null 92  null  FRSA_P Unsold 
site1 T2B Pre null  null 36  null  FRSA_P Unsold 
site1 T2B PRI null  null 173  null  FRSA_P Unsold 
site1 T2B SPE null  null 56  null  FRSA_P Unsold 
site1 T2B P Complete FRSA 2  2013-01-01 FRSA_P Sold 
site1 T2B Pre Complete FRSA 2  2013-01-01 FRSA_P Sold 
site1 T2B PRI Complete FRSA 2  2013-01-01 FRSA_P Sold 
site1 T2B P Complete FRSA 1  2013-03-05 FRSA_P Sold 
site1 T2B P Complete FRSA 3  2014-01-01 FRSA_P Sold 
site1 T2B Pre Complete FRSA 4  2014-01-01 FRSA_P Sold 
site1 T3B P  null  null 69  null  FRSA_P Unsold 
site1 T3B Pre null  null 26  null  FRSA_P Unsold 
site1 T3B PRI null  null 125  null  FRSA_P Unsold 
site1 T3B SPE null  null 40  null  FRSA_P Unsold 
site1 T3B Pre Complete FRSA 2  2013-01-01 FRSA_P Sold 
site1 T3B P Complete FRSA 1  2014-01-01 FRSA_P Sold 
site1 T3B Pre Complete FRSA 2  2014-01-01 FRSA_P Sold 

然后以某种方式得到如下图所示的报告。如果InvStatus未售出,报告应该返回未售出,否则为CTRSTAT。

Result after grouping by columns and rows with totals

请不要注意总计和总计,使用其他数据的图像是从Excel。只是为了获得所需结果的样本。

编辑:日期列对应于一整年,所以例如2013-03-05的日期列属于01/01/2013列。在无效日期的情况下,他们将去到显示的最后一年,在这种情况下01/01/2014,但可以是2015年,无论上一次显示哪个周期。

我已经尝试了几种不同的方法,使用GROUP BY连同各种类型的GROUPINGSETS,但都没有工作。 CUBEROLLUP没有用,或者至少我没有设法得到正确的结果。也许只是不可能,至少不是一个简单的方法。

下面是我尝试过的许多查询之一的样本,试图扭曲它以获得类似报告的内容,但仍然没有任何结果。

SELECT 
     sitename, rtype, season, ctrstat, ctrtype, SUM(units) 
     ,startdate, invstat 
    FROM tt 
GROUP BY 
GROUPING SETS ((sitename,InvStat,ctrstat) 
       ,(RType,ctrtype,season,startdate) 
       ,() 
      ) 

编辑:也许应该更好地使用SSRS完成这个任务?

+1

有趣的问题。这并不容易,但这是可能的。在开始分组之前,您必须首先进行一些旋转以提取所需的列。如果我在接下来的几个小时内获得一些空闲时间,我会尝试给你一些疑问,但不能承诺。 – 2013-04-23 09:45:36

+1

几个问题:您的startdate如何转换为哪些列数据所属? 2013年或2014年?特别为未售出的地方它是NULL? 2013-03-05在哪里?您能否根据您发布的确切数据提供预期结果? – 2013-04-23 09:55:22

+0

谢谢@NenadZivkovic,检查新的编辑。在某些时候,我考虑过转向,但我甚至不知道如何解决这个问题。 – Yaroslav 2013-04-23 10:07:35

回答

2

正如你在编辑中提到的那样,我认为要做到这一点我是SSRS的出路。您可以使用矩阵轻松创建您正在查找的报告。通过使用SQL小提琴中给出的数据,您可以快速获得如下所示的内容。

编辑:增加了总价值 enter image description here

enter image description here

+0

Whoa!做得很好。我是使用SSRSm的新手,你能指出一些链接,我可以找到这样的东西吗?不只是一个教程,因为它将涵盖我已经知道的基本内容。 – Yaroslav 2013-04-23 11:49:17

+1

此报告是通过在不同字段上使用分组创建的。这个msdn页面是分组和添加总计的很好介绍。这基本上是你在之后:http://msdn.microsoft.com/en-us/library/ms170712.aspx – 2013-04-23 11:53:35

+0

好,我正在去做它的方式,列组有点fustrating,但我想我会很快完成它。再次感谢,这是更快的方式,因为我可以重新使用存储过程为其他报告返回的表而无需修改它。 – Yaroslav 2013-04-23 15:33:34

1

虽然SSRS可能是一个更好的选择,在这里是如何将其与SQL查询来完成。最后,将两者结合起来可能是最好的解决方案。

WITH CTE_Pivot AS 
(
    SELECT 
     sitename 
     ,rtype 
     ,season 
     ,CASE WHEN invstat = 'Sold' AND ctrStat = 'Complete' AND YEAR(startdate)=2013 THEN units ELSE 0 END AS Complete2013 
     ,CASE WHEN invstat = 'Sold' AND ctrStat = 'Complete' AND (YEAR(startdate)=2014 OR startdate IS NULL) THEN units ELSE 0 END AS Complete2014 
     ,CASE WHEN invstat = 'Unsold' AND YEAR(startdate)=2013 THEN units ELSE 0 END AS Unsold2013 
     ,CASE WHEN invstat = 'Unsold' AND (YEAR(startdate)=2014 OR startdate IS NULL) THEN units ELSE 0 END AS Unsold2014 
     ,units AS Total 
    FROM tt 
) 
SELECT sitename,rtype,season 
    ,SUM(Complete2013) AS Complete2013 
    ,SUM(Complete2014) AS Complete2014 
    ,SUM(Unsold2013) AS Unsold2013 
    ,SUM(Unsold2014) AS Unsold2014 
    ,SUM(Total) AS GrandTotal 
FROM CTE_Pivot 
GROUP BY GROUPING SETS ((sitename,rtype,season),(sitename,rtype),sitename) 

SQLFiddle DEMO

第一部分是要透视列。这是相当简单的方法,不使用PIVOT函数,而是在CASE声明中声明每个列的条件。它假设您有可能的值(和列)的固定数量可能不完美,但创建dynamic columns require dynamic SQL会使此查询达到全新的复杂程度。

毕竟在这种情况下,我真的不认为你会有很多不同的CTRSTAT值,我想你知道所有可能的值。多年来有点问题,但我仍然认为没有那么多。你也许可以选择“今年,最后一年,下一年”,以使它在未来更具适应性。

查询的第二部分只是使用简单的分组集进行分组。 ROLLUP将与此相同。

+0

经过测试,也在工作,你有我的赞赏。我更愿意使用@Nighty_给出的答案,这样我可以重新使用存储过程来处理其他报告。我将保存此tsql样本以满足其他需求,再次感谢。 – Yaroslav 2013-04-23 15:34:59