使用pivot动态添加会计月的sql查询
我有一个根据会计年度生成报告的存储过程。使用pivot动态添加会计月的sql查询,sql,sql-server-2008,pivot,Sql,Sql Server 2008,Pivot,我有一个根据会计年度生成报告的存储过程。 这里的会计年度和会计月份来自数据库,现在我在动态生成此报告时遇到了问题,正如您所看到的,我已修复了月份-年度,这不是一个好的做法,我希望以某种方式,如果我更改了数据库中的会计月份,那么我的报告将相应地反映出来。您将需要使用动态SQL来执行此操作这大致代码如下所示: ALTER PROCEDURE [dbo].[_sp_GetDMActivityTrackerReport] @CoachId VARCHAR(7), @Month INT, @FiscalY
这里的会计年度和会计月份来自数据库,现在我在动态生成此报告时遇到了问题,正如您所看到的,我已修复了月份-年度,这不是一个好的做法,我希望以某种方式,如果我更改了数据库中的会计月份,那么我的报告将相应地反映出来。您将需要使用动态SQL来执行此操作这大致代码如下所示:
ALTER PROCEDURE [dbo].[_sp_GetDMActivityTrackerReport]
@CoachId VARCHAR(7),
@Month INT,
@FiscalYear INT
AS
BEGIN
INSERT @FiscalMonth (ID,Month,NbHolidays,MonthDate,TotalDays)
EXECUTE dbo._sp_GetFiscalMonths @Month, @FiscalYear
SELECT PreparationID,CoachId,UserID, MemberID,
[Rep Name], isnull(April,0) April, isnull(May,0) May, isnull(June,0)June,
isnull(July,0) July, isnull(August,0) August, isnull(September,0) September,
isnull(October,0) October, isnull(November,0) November,
isnull(December,0) December, isnull(January,0) January, isnull(February,0) February,
isnull(March,0) March,isnull((isnull(November,0) + isnull(December,0) +
isnull(January,0) + isnull(February,0) + isnull(March,0) + isnull(April,0) +
isnull(May,0) + isnull(June,0) + isnull(July,0) + isnull(August,0) +
isnull(September,0) + isnull(October,0)),0) as [Total Field TIME]
FROM
(
SELECT up.PreparationID,tt.UserId [CoachId],up.UserID, utm.MemberID,
(ui.FirstName + ' ' + ui.LastName) AS [Rep Name],DateName(Month,nft.MonthPeriodStart) [Month], sum(nft.Quantity) [Days]
FROM TransferedTime tt
INNER JOIN UPreparation up ON tt.PreparationID = up.PreparationID
RIGHT JOIN UTeamMembers utm ON tt.UserId = utm.CoachID AND utm.MemberID = up.UserID
INNER JOIN UserInfo ui ON utm.MemberID = ui.UserID
LEFT JOIN NonFieldTime nft ON nft.UserId = tt.UserId
AND tt.MonthPeriodFrom = nft.MonthPeriodStart
AND datename(Month,nft.MonthPeriodStart) + '-'+ substring(datename(Year,nft.MonthPeriodStart),3,2) IN
(SELECT Month +'-' +substring(datename(Year,MonthDate),3,2) [Months] FROM @FiscalMonth)
WHERE utm.MemberID IN (SELECT MemberID FROM UTeamMembers WHERE CoachID = @CoachId)
GROUP BY up.PreparationID,tt.UserId,up.UserID, utm.MemberID,
(ui.FirstName + ' ' + ui.LastName),DateName(Month,nft.MonthPeriodStart)) src
pivot
(
sum(Days)
for Month in (April, May, June, July, August, September, October,November, December, January, February, March)
)
piv
@Fiscalmonth returns:
Id, Month, NbHolidays, MonthDate
1 April 1 4/1/2012
2 May 2 5/1/2012
3 June 3 6/1/2012
4 July 4 7/1/2012
5 August 5 8/1/2012
6 September 6 9/1/2012
7 October 7 10/1/2012
8 November 8 11/1/2012
9 December 9 12/1/2012
10 January 10 1/1/2013
11 February 11 2/1/2013
12 March 12 3/1/2013
我的建议不是使用temp table@FiscalMonth,而是为此创建一个永久的表。使用动态sql时,查询perm表比查询temp表要简单得多。临时表可能超出了动态查询的范围 Oracle中有PIVOT XML选项,允许您避免硬编码。我不确定SQL Server中是否有这样的选项。您可以编写smth lk,也可以编写Oracle查询:
ALTER PROCEDURE [dbo].[_sp_GetDMActivityTrackerReport]
@CoachId VARCHAR(7),
@Month INT,
@FiscalYear INT
AS
BEGIN
INSERT @FiscalMonth (ID,Month,NbHolidays,MonthDate,TotalDays)
EXECUTE dbo._sp_GetFiscalMonths @Month, @FiscalYear
DECLARE @cols AS NVARCHAR(MAX),
@colsNull AS NVARCHAR(MAX),
@colsSum AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT distinct ',' + QUOTENAME(DateName(Month,nft.MonthPeriodStart))
from NonFieldTime nft
where datename(Month,nft.MonthPeriodStart) + '-'+ substring(datename(Year,nft.MonthPeriodStart),3,2)
IN (SELECT Month +'-' +substring(datename(Year,MonthDate),3,2) [Months]
FROM +@FiscalMonth)
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'')
select @colsNull = STUFF((SELECT distinct ', IsNull(' + QUOTENAME(DateName(Month,nft.MonthPeriodStart))+', 0) as '+DateName(Month,nft.MonthPeriodStart)
from NonFieldTime nft
where datename(Month,nft.MonthPeriodStart) + '-'+ substring(datename(Year,nft.MonthPeriodStart),3,2)
IN (SELECT Month +'-' +substring(datename(Year,MonthDate),3,2) [Months]
FROM +@FiscalMonth)
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)') ,1,1,'')
select @colsSum = STUFF((SELECT distinct '+ IsNull(' + QUOTENAME(DateName(Month,nft.MonthPeriodStart))+', 0)'
from NonFieldTime nft
where datename(Month,nft.MonthPeriodStart) + '-'+ substring(datename(Year,nft.MonthPeriodStart),3,2)
IN (SELECT Month +'-' +substring(datename(Year,MonthDate),3,2) [Months]
FROM +@FiscalMonth)
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)') ,1,1,'')+' as [Total Field TIME] '
set @query = 'SELECT PreparationID,CoachId,UserID, MemberID,
[Rep Name], ' + @colsNull + ', '+ @colsSum+'
from
(
SELECT up.PreparationID,
tt.UserId [CoachId],
up.UserID, utm.MemberID,
(ui.FirstName + '' '' + ui.LastName) AS [Rep Name],
DateName(Month,nft.MonthPeriodStart) [Month],
sum(nft.Quantity) [Days]
FROM TransferedTime tt
INNER JOIN UPreparation up
ON tt.PreparationID = up.PreparationID
RIGHT JOIN UTeamMembers utm
ON tt.UserId = utm.CoachID AND utm.MemberID = up.UserID
INNER JOIN UserInfo ui
ON utm.MemberID = ui.UserID
LEFT JOIN NonFieldTime nft
ON nft.UserId = tt.UserId
AND tt.MonthPeriodFrom = nft.MonthPeriodStart
AND datename(Month,nft.MonthPeriodStart) + ''-''+ substring(datename(Year,nft.MonthPeriodStart),3,2) IN
(SELECT Month +''-'' +substring(datename(Year,MonthDate),3,2) [Months]
FROM +@FiscalMonth)
WHERE utm.MemberID IN (SELECT MemberID
FROM UTeamMembers
WHERE CoachID = '+@CoachId+')
GROUP BY up.PreparationID,tt.UserId,up.UserID, utm.MemberID,
(ui.FirstName + '' '' + ui.LastName),DateName(Month,nft.MonthPeriodStart)
) x
pivot
(
sum(Days)
for Month in (' + @cols + ')
) p '
execute(@query)
将状态替换为月份等。。。
输出:
Oracle示例:
因此,您希望在不硬编码数据透视表逻辑中的月份的情况下完全按照此处所做的操作?如果解决了我的问题,则答案是可以接受的@Love2Learn您应该将别名更改为@Love2Learn这完全是错误的做法。如果你想获得声誉,写下好的答案,注意确保你有一个友好的态度,在你知道之前,你将获得你所需要的一切。作为一个混蛋,我只会在你注意的情况下帮你。答案绝对是错误的。作为一个例子,我将指出我的答案比其他大多数人晚,我获得了所有人中最多的赞成票,而辛格的回答可能非常有助于获得正确的语法,那就是使用表和一些示例数据创建一个。这超出了范围,但是是的,解决这个问题,这就是你想要的。谢谢@BlueFoots它几乎可以工作。我唯一想知道的是,现在我在非字段时间表中只有两个月的数据,即12月和1月,所以它显示了他们的结果,但我也必须显示其余的月份。@divyanssingh因为你在动态地提取值,所以数据透视列将以你的表格中的内容为基础。如果你想确保每个月都包括在内,或者使用硬编码版本的查询,那么你需要加入一份一年中所有月份的列表。@Divyanssingh如果你需要所有月份,那么为什么你说固定月份是不好的做法,这正是你需要的。您不需要使用动态sql来实现that@lamak事实上,现在我有一个财政月,从4月份开始,未来可能是6月份,对于其他客户机,这就是为什么我希望它转换为动态查询。
SELECT count(decode(state,'FL',custid)) "FL"
, count(decode(state,'NY',custid)) "NY"
, count(decode(state,'CA',custid)) "CA"
FROM scott.customer
GROUP BY state
/
FL NY CA
--- --- ---
0 2 0
5 0 8
SELECT * FROM
(
SELECT product_code, quantity
FROM pivot_test
)
PIVOT XML
(
SUM(quantity) AS sum_quantity
FOR (product_code) IN (SELECT DISTINCT product_code
FROM pivot_test
WHERE id < 10)
)
/