[英]how can I get data from every month from past one year in t-sql and each month should be in different column
我想要過去1年的數據,例如今天是2014年2月5日,我需要2013年5月,2013年6月的數據。直到2014年4月作為單獨的列。 如果有人可以在t-sql中使用此代碼,這對我將非常有幫助。 謝謝
好的,我想要數據。 以下是我的專欄
created date
------------
02-05-2013
16-05-2013
05-06-2013
22-07-2013
01-08-2013
09-08-2013
02-09-2013
03-10-2013
19-11-2013
11-12-2013
03-01-2014
29-02-2014
15-03-2014
19-04-2014
我想要結果
May 2013 June 2013 July 2013 August 2013 till April 2014
-------- --------- --------- ----------- ----------
02-05-2013 05-06-2013 22-07-2013 01-08-2013 19-04-2014
16-05-2013 09-08-2013
而且我想動態創建列 ,這對我的查詢非常重要
盡管每個人都很快建議使用PIVOT
,但這在這里真的行不通,因為PIVOT
需要將每一列匯總為該月和年份的一個(最大,最小,任何日期)日期。
我給了這個問題一些注意,因為它實際上是一個有趣的挑戰。 現實情況是,最好通過某些報告工具(例如SSRS)來完成此操作,因為您的輸出實際上是時間軸報告。
由於需要動態列之類的東西,因此我真的看不到沒有變量和一些動態sql怎么辦,所以假設這是可以接受的,下面的內容將經過測試,並將完全輸出您所描述的內容。 它實際上創建了12個CTE表,每個表包含一個月和一年的日期(從運行sql的任何月份和年份開始向后計數)。 然后,它只需使用所有表的FULL OUTER JOIN
創建報告。 但是,如果僅將12個表完全連接在一起,則每一列的值將在幾行中隨機排列,並且在許多行之間存在空值。 要在頂部的每一列中排列日期,必須添加一個基表,該基表具有每個月/年表可以加入的順序編號。 對於任何給定的年/月,最多生成最大數量的序列號。 (注意:對於基數表, LEFT OUTER JOIN
也足夠了...)
假定表名稱為dbo.MyTable
,日期dbo.MyTable
CreatedDate
:
DECLARE @cteSql nvarchar(MAX) = '';
DECLARE @tblSql nvarchar(MAX) = '';
DECLARE @frmSql nvarchar(MAX) = '';
DECLARE @colNm varchar(10);
DECLARE @tblNm varchar(3);
DECLARE @i int = 0;
/* today's date */
DECLARE @td date = GETDATE();
/* max number of dates per yr/mo */
DECLARE @maxItems int = (SELECT MAX(CNT) FROM (SELECT COUNT(*) AS CNT FROM dbo.MyTable GROUP BY YEAR(CreatedDate), MONTH(CreatedDate)) T)
/* a table of sequential numbers up to the max per yr/mo; this is so the full outer join is laid out neatly */
SET @cteSql = 'WITH T(id) AS( SELECT id = 1 UNION ALL SELECT id + 1 FROM T WHERE id + 1 <= ' + CAST(@maxItems AS varchar(16)) + ')';
/* count down from current date to past 12 months */
WHILE @i > -12
BEGIN
/* a simple name for each CTE: T0, T1, T2 etc */
SET @tblNm = 'T' + CAST((@i*-1) AS varchar(2));
/* rpt column names; [Jan 2014], [Feb 2014] etc */
SET @colNm = '[' + RIGHT(CONVERT(varchar(11), DATEADD(m, @i, @td), 106),8) + ']';
/* each CTE contains a sequential id and the dates belonging to that month and yr */
SET @cteSql += ', ' + @tblNm + '(id, ' + @colNm + ')'
+ ' AS (SELECT ROW_NUMBER() OVER(ORDER BY CreatedDate) AS id, CreatedDate FROM dbo.MyTable WHERE YEAR(CreatedDate) = ' + CAST(YEAR(DATEADD(m, @i, @td)) AS varchar(4))
+ ' AND MONTH(CreatedDate) = ' + CAST(MONTH(DATEADD(m, @i, @td)) AS varchar(2)) + ')';
/* this will eventually be the SELECT statement for the report...just the month columns, not the id */
SET @tblSql = ', ' + @colNm + @tblSql;
/* concatenate all the columns using FULL OUTER JOIN with the first table of simple sequential numbers as the driver */
SET @frmSql += ' FULL OUTER JOIN ' + @tblNm + ' ON T.id = ' + @tblNm + '.id ';
SET @i -= 1;
END
/* put all the sql together */
SET @tblSql = @cteSql + ' SELECT' + STUFF(@tblSql, 1, 1, '') + ' FROM T ' + @frmSql
/* view the generated sql */
-- SELECT @tblSql AS X
/* this should generate the report you described above, showing the last 12 months from whatever date you run it */
EXECUTE (@tblSql)
輸出:
Jun 2013 Jul 2013 Aug 2013 Sep 2013 Oct 2013 Nov 2013 Dec 2013 Jan 2014 Feb 2014 Mar 2014 Apr 2014 May 2014
---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
2013-06-05 2013-07-22 2013-08-01 2013-09-02 2013-10-03 2013-11-19 2013-12-11 2014-01-03 2014-02-28 2014-03-15 2014-04-19 NULL
2013-06-07 NULL 2013-08-09 NULL NULL NULL NULL NULL NULL NULL NULL NULL
NULL NULL 2013-08-10 NULL NULL NULL NULL NULL NULL NULL NULL NULL
事實證明,生成的sql在概念上與@Hogan所建議的類似,盡管我最初並未意識到。 它實際上只是添加了動態命名以及按年/月而不是僅按月進行的隔離。
這是一種無需動態調整即可完成的方法。 我只在2013年這樣做,您可以看到添加更多列所需的內容:
(工作提琴: http ://sqlfiddle.com/#!6/ d9797/1 )
with nums as
(
select [create date],
MONTH([create date]) as M,
ROW_NUMBER() OVER (ORDER BY [create date] ASC) as RN
from table1
where MONTH([create date]) =1
union all
select [create date],
MONTH([create date]) as M,
ROW_NUMBER() OVER (ORDER BY [create date] ASC) as RN
from table1
where MONTH([create date]) =2
union all
select [create date],
MONTH([create date]) as M,
ROW_NUMBER() OVER (ORDER BY [create date] ASC) as RN
from table1
where MONTH([create date]) =3
union all
select [create date],
MONTH([create date]) as M,
ROW_NUMBER() OVER (ORDER BY [create date] ASC) as RN
from table1
where MONTH([create date]) =4
union all
select [create date],
MONTH([create date]) as M,
ROW_NUMBER() OVER (ORDER BY [create date] ASC) as RN
from table1
where MONTH([create date]) =5
union all
select [create date],
MONTH([create date]) as M,
ROW_NUMBER() OVER (ORDER BY [create date] ASC) as RN
from table1
where MONTH([create date]) =6
union all
select [create date],
MONTH([create date]) as M,
ROW_NUMBER() OVER (ORDER BY [create date] ASC) as RN
from table1
where MONTH([create date]) =7
union all
select [create date],
MONTH([create date]) as M,
ROW_NUMBER() OVER (ORDER BY [create date] ASC) as RN
from table1
where MONTH([create date]) =8
union all
select [create date],
MONTH([create date]) as M,
ROW_NUMBER() OVER (ORDER BY [create date] ASC) as RN
from table1
where MONTH([create date]) =9
union all
select [create date],
MONTH([create date]) as M,
ROW_NUMBER() OVER (ORDER BY [create date] ASC) as RN
from table1
where MONTH([create date]) =10
union all
select [create date],
MONTH([create date]) as M,
ROW_NUMBER() OVER (ORDER BY [create date] ASC) as RN
from table1
where MONTH([create date]) =11
union all
select [create date],
MONTH([create date]) as M,
ROW_NUMBER() OVER (ORDER BY [create date] ASC) as RN
from table1
where MONTH([create date]) =12
),maxrn as
(
select MAX(RN) as maxnum from nums
), rowNumbers as
(
select 1 as RN
union all
select RN+1 AS RN
from rowNumbers
where RN < (select maxnum from maxrn)
)
SELECT
nJan.[create date] as [Jan 2013],
nFeb.[create date] as [Feb 2013],
nMar.[create date] as [Mar 2013],
nApr.[create date] as [Apr 2013],
nMay.[create date] as [May 2013],
nJun.[create date] as [Jun 2013],
nJul.[create date] as [Jul 2013],
nAug.[create date] as [Aug 2013],
nSep.[create date] as [Sep 2013],
nOct.[create date] as [Oct 2013],
nNov.[create date] as [Nov 2013],
nDec.[create date] as [Dec 2013]
FROM rowNumbers n
LEFT JOIN nums nJan ON n.RN = nJan.RN and nJan.M = 1
LEFT JOIN nums nFeb ON n.RN = nFeb.RN and nFeb.M = 2
LEFT JOIN nums nMar ON n.RN = nMar.RN and nMar.M = 3
LEFT JOIN nums nApr ON n.RN = nApr.RN and nApr.M = 4
LEFT JOIN nums nMay ON n.RN = nMay.RN and nMay.M = 5
LEFT JOIN nums nJun ON n.RN = nJun.RN and nJun.M = 6
LEFT JOIN nums nJul ON n.RN = nJul.RN and nJul.M = 7
LEFT JOIN nums nAug ON n.RN = nAug.RN and nAug.M = 8
LEFT JOIN nums nSep ON n.RN = nSep.RN and nSep.M = 9
LEFT JOIN nums nOct ON n.RN = nOct.RN and nOct.M = 10
LEFT JOIN nums nNov ON n.RN = nNov.RN and nNov.M = 11
LEFT JOIN nums nDec ON n.RN = nDec.RN and nDec.M = 12
ORDER BY n.RN ASC
OOOPS這個已經有答案T_T,
但是,如果您有空的話,請嘗試一下。 :)
在這種情況下要使用很多東西:
聲明@xCol nvarchar(max);
--Begin create column
with cte as
(
select 1 as id,
aa.month as mm, aa.Year
--,aa.xmonth as mmm
, aa.ord
from
(
select
xdate
,Year(xdate) as Year
--,month(xdate) as xmonth
, substring(convert(nvarchar(max),xdate,106),3,len(convert(nvarchar(max),xdate,106))) as month
,convert(nvarchar(6), xdate,112) as ord
from tempData vv
) aa
group by aa.ord, aa.month,aa.Year
--order by aa.Year
)
select
distinct
--c.id,
@xCol = stuff(
(
select ',' + c2.mm
from cte c2
where c.id = c2.id
for xml path ('')
),1,0,''
)
from cte c
;
set @xCol= SUBSTRING(@xCol,2, len(@xCol))
select @xCol = '[' + replace(@xCol,',','],[') + ']'
--select @xCol as '@columns', len(@xCol)
--END CREATE COLUMNS
--CREATE INPUT STRING
Declare @tbl_inputstr table
(
id int,
xstr nvarchar(max)
)
;
with cte as
(
select
a.xdate, a.month
,row_number() over(partition by a.month order by a.xdate) as xrow
from
(
select
xdate
,Year(xdate) as Year
,month(xdate) as xmonth
,convert(nvarchar(6),xdate,112) as month2
, substring(convert(nvarchar(max),xdate,106),3,len(convert(nvarchar(max),xdate,106))) as month
from tempData
) a
)
insert into @tbl_inputstr(id,xstr)
select distinct c.xrow as id,
' Insert into @tempData (' + substring(stuff(
(
select ',[' + cast(c2.month as nvarchar(max)) + ']'
from cte c2
where c.xrow = c2.xrow
for xml path ('')
),1,0,''
),2,len(stuff(
(
select ',[' + cast(c2.month as nvarchar(max)) + ']'
from cte c2
where c.xrow = c2.xrow
for xml path ('')
),1,0,''
))) + ')'
+' Values(' + Substring(stuff(
(
select ',''' + cast(c2.xdate as nvarchar(max)) + ''''
from cte c2
where c.xrow = c2.xrow
for xml path ('')
),1,0,''
),2,len(stuff(
(
select ',''' + cast(c2.xdate as nvarchar(max)) + ''''
from cte c2
where c.xrow = c2.xrow
for xml path ('')
),1,0,''
))) + ')'
from cte c
order by c.xrow;
select * from @tbl_inputstr
Declare @inputStr nvarchar(max)
select @inputStr =
substring(stuff
(
(
select ';' + xstr
from @tbl_inputstr
for xml path('')
),1,0,''
),2, len(stuff
(
(
select ';' + xstr
from @tbl_inputstr
for xml path('')
),1,0,''
))
)
select @inputStr= 'Declare @tempData Table (' +replace(@xCol,']', '] nvarchar(max)') + ');' + @inputStr
+ '; select ' + @xCol
+ ' from @tempData'
exec(@inputStr)
--END INPUT STRING
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.