SQL Below工作gr8,但顺序,如何设置放置Jan,Feb,Mar命令。我知道我需要在序数月份执行此操作,但是当我按顺序添加时,我会收到错误 ' ORDER BY子句在视图,内联函数,派生表,子查询和公共中无效表表达式,除非还指定了TOP,OFFSET或FOR XML。'
结果如下:
DECLARE @cols AS NVARCHAR(MAX)
DECLARE @query AS NVARCHAR(MAX)
SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(year(TransactionDateTime))
FROM Quotations
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SET @query =
'SELECT *
FROM (
SELECT
left(datename(month,TransactionDateTime),3) as [month], year(TransactionDateTime) as [year],
isnull(count(*),0) as Total
FROM quotations
group by left(datename(month,TransactionDateTime),3), year(TransactionDateTime)
) as s
PIVOT
(
SUM(Total)
FOR [year] IN (' + @cols + ')
) AS QuotationResults'
EXECUTE(@query)
答案 0 :(得分:1)
如错误所示,除非订单有原因(TOP
,FOR XML
等),否则您无法订购子查询。这样做的原因是,只是因为您已经订购了子查询,所以没有理由在外部查询中维护此顺序。 SQL Server基本上告诉您,ORDER BY
毫无意义,因此无效。
解决方案是简单地将一个带月号的列添加到您的子查询s
,然后您可以按顺序排序。您还需要明确说明您的选择列表,以确保此新列不会出现在其中:
DECLARE @cols AS NVARCHAR(MAX);
DECLARE @query AS NVARCHAR(MAX);
SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(year(TransactionDateTime))
FROM Quotations
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'');
SET @query =
'SELECT [month], ' + @Cols + '
FROM (
SELECT
left(datename(month,TransactionDateTime),3) as [month],
datepart(month,TransactionDateTime) as [monthNum],
year(TransactionDateTime) as [year],
isnull(count(*),0) as Total
FROM quotations
group by left(datename(month,TransactionDateTime),3), datepart(month,TransactionDateTime), year(TransactionDateTime)
) as s
PIVOT
(
SUM(Total)
FOR [year] IN (' + @cols + ')
) AS QuotationResults
ORDER BY QuotationResults.MonthNum;';
EXECUTE(@query);
<强>附录强>
ISNULL()
不会捕获空值,因为在使用ISNULL()
时它们不存在。 COUNT(*)
永远不会返回null,因此您的ISNULL()
实际上是多余的。
如果你有一个非常简单的例子:
TransactionDateTime
----------------------
2015-01-01
2015-02-01
2015-02-01
2014-03-01
要向前跳一步,在您的支点后,您将最终得到:
Month 2014 2015
------------------------
Jan NULL 1
Feb NULL 2
Mar 1 NULL
所以你最终得到了NULL值,现在回到一步,如果你在汇总后看结果:
Month MonthNum Year Total
-----------------------------------
Jan 1 2015 1
Feb 2 2015 2
Mar 3 2014 1
因此2014年1月或2月没有行,因此SUM(NULL)
将产生NULL
。我建议将所有聚合留给pivot功能。所以你的非动态查询看起来像:
SELECT pvt.[Month], pvt.[2014], pvt.[2015]
FROM ( SELECT [Month] = LEFT(DATENAME(MONTH, TransactionDateTime), 3),
[MonthNum] = DATEPART(MONTH, TransactionDateTime),
[Year] = DATEPART(YEAR, TransactionDateTime),
Value = 1
FROM Quotations
) AS t
PIVOT
(
COUNT(Value)
FOR [year] IN ([2014], [2015])
) AS pvt
ORDER BY pvt.MonthNum;
并加入动态SQL:
DECLARE @cols AS NVARCHAR(MAX);
DECLARE @query AS NVARCHAR(MAX);
SET @cols = STUFF((SELECT DISTINCT ',' + QUOTENAME(DATEPART(YEAR, TransactionDateTime))
FROM Quotations
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'');
SET @query =
'SELECT pvt.[Month], ' + @cols + '
FROM ( SELECT [Month] = LEFT(DATENAME(MONTH, TransactionDateTime), 3),
[MonthNum] = DATEPART(MONTH, TransactionDateTime),
[Year] = DATEPART(YEAR, TransactionDateTime),
Value = 1
FROM Quotations
) AS t
PIVOT
(
COUNT(Value)
FOR [year] IN (' + @cols + ')
) AS pvt
ORDER BY pvt.MonthNum;
(
SUM(Total)
FOR [year] IN (' + @cols + ')
) AS QuotationResults
ORDER BY QuotationResults.MonthNum;';
EXECUTE sp_executesql @query;