[英]how can I get data from every month from past one year in t-sql and each month should be in different column
I want data from past 1 year, for example today is 02-05-2014, i need data from May 2013, June 2013..till April 2014 as separate columns. 我想要过去1年的数据,例如今天是2014年2月5日,我需要2013年5月,2013年6月的数据。直到2014年4月作为单独的列。 If anybody can help with this code in t-sql that will be very helpful for me. 如果有人可以在t-sql中使用此代码,这对我将非常有帮助。 Thanks 谢谢
ok here i want the data. 好的,我想要数据。 below is my column 以下是我的专栏
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
I want the result as 我想要结果
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
and also I want to make Columns dynamically which is very important for my query 而且我想动态创建列 ,这对我的查询非常重要
Although everyone was quick to suggest using PIVOT
, that really won't work here because PIVOT
would need to aggregate each column into one (max, min, whatever) date for that month and year. 尽管每个人都很快建议使用PIVOT
,但这在这里真的行不通,因为PIVOT
需要将每一列汇总为该月和年份的一个(最大,最小,任何日期)日期。
I gave this question some attention because it was actually an interesting challenge. 我给了这个问题一些注意,因为它实际上是一个有趣的挑战。 The reality is, this is best done by some reporting tool, such as SSRS, because your output is really a timeline report. 现实情况是,最好通过某些报告工具(例如SSRS)来完成此操作,因为您的输出实际上是时间轴报告。
Because of the requirement for dynamic columns and such, I really don't see how this can be done without variables and some dynamic sql, so assuming that is acceptable, the following is tested and will output exactly what you described. 由于需要动态列之类的东西,因此我真的看不到没有变量和一些动态sql怎么办,所以假设这是可以接受的,下面的内容将经过测试,并将完全输出您所描述的内容。 It essentially creates 12 CTE tables, each containing the dates for a month and year, (counting backwards from whatever month and year you run the sql). 它实际上创建了12个CTE表,每个表包含一个月和一年的日期(从运行sql的任何月份和年份开始向后计数)。 It then creates the report simply by using a FULL OUTER JOIN
of all the tables. 然后,它只需使用所有表的FULL OUTER JOIN
创建报告。 However, if you full joined just the 12 tables, each column would have its values randomly over several rows with many nulls in betweeen. 但是,如果仅将12个表完全连接在一起,则每一列的值将在几行中随机排列,并且在许多行之间存在空值。 To line the dates in each column up at the top, it was necessary to add a base table with sequential numbers that each mo/yr table can join on. 要在顶部的每一列中排列日期,必须添加一个基表,该基表具有每个月/年表可以加入的顺序编号。 The sequential numbers are generated up to the max number of dates for any given mo/yr. 对于任何给定的年/月,最多生成最大数量的序列号。 (Note: with the base number table, a LEFT OUTER JOIN
would have sufficed as well...) (注意:对于基数表, LEFT OUTER JOIN
也足够了...)
This assumes the table name is dbo.MyTable
and the date column is CreatedDate
: 假定表名称为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)
Output: 输出:
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
As it turns out, the sql generated is conceptually similar to what @Hogan suggested, although I did not realize it at first. 事实证明,生成的sql在概念上与@Hogan所建议的类似,尽管我最初并未意识到。 It really just adds the dynamic naming plus the segregation by yr/mo and not just month. 它实际上只是添加了动态命名以及按年/月而不是仅按月进行的隔离。
Here is a way to do it without a dynamic pivot. 这是一种无需动态调整即可完成的方法。 I only did it for 2013, you can see what is needed to add more columns: 我只在2013年这样做,您可以看到添加更多列所需的内容:
(working fiddle: http://sqlfiddle.com/#!6/d9797/1 ) (工作提琴: 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 this already have an answer T_T, OOOPS这个已经有答案T_T,
but try this if you have a free time. 但是,如果您有空的话,请尝试一下。 :) :)
use a lot of things in this case: 在这种情况下要使用很多东西:
declare @xCol nvarchar(max); 声明@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.