根据下表上
Title Jul-10 Aug-10 Sep-10 Oct-10 Nov-10 Dec-10 Jan-11 Feb-11 Mar-11 Apr-11 May-11 Jun-11
--------------------------------------------------------------------------------------------
A Null M1 Null M2 Null Null Null Null M3 Null Null Null
B Null M1 Null Null Null Null M2 Null Null Null Null Null
C Null Null Null Null Null M1 Null Null Null Null Null Null
如何选择只在一定的范围之间的列。
For instance if input variables are:
-------------------------------------
@start = 'Oct-10'
@end = 'Apr-11'
然后输出将是:
Title Oct-10 Nov-10 Dec-10 Jan-11 Feb-11 Mar-11 Apr-11
-----------------------------------------------------------------
A M2 Null Null Null Null M3 Null
B Null Null Null M2 Null Null Null
C Null Null M1 Null Null Null Null
这里有一个简单的方法做你的支点,使用名为pivot_query一个方便的存储过程( 代码是在这里 , 例子在这里 )。 你用你的开始和结束日期标准,这样一来,首先限制对数据进行转动,从而限制你转动后得到的列。
该fn_MonthRange()函数是一个递归CTE,除了提供日期的表一个月的开始和结束日期,然后您可以OUTER连接到你的数据之间。 这将填补任何缺少个月。
( fn_DateRange()类似,但适用于每一个小时任意时间段,如“每15分钟”,每3天等)
create table #testdata
(
id integer,
Title varchar(20),
TheDate datetime,
Metadata varchar(20)
)
go
insert into #testdata values(1,'A','08/01/2010','M1')
insert into #testdata values(1,'A','10/05/2010','M2')
insert into #testdata values(1,'A','03/15/2011','M3')
insert into #testdata values(2,'B','09/20/2010','M1')
insert into #testdata values(2,'B','01/15/2011','M2')
insert into #testdata values(3,'C','12/15/2010','M1')
go
declare @mySQL varchar(MAX);
declare @StartDate varchar(20);
declare @EndDate varchar(20);
set @StartDate = '08/01/2010';
set @EndDate = '03/15/2011';
set @mySQL = '
select
id,
Title,
Left(Datename(month, TheDate),3) + ''-'' + right(cast(Year(theDate) as varchar(4)),2) monyr,
Metadata
from
dbo.fn_MonthRange( ''' + @StartDate + ''',''' + @EndDate + ''') dr
LEFT OUTER JOIN #testdata td
on (td.TheDate between dr.startdate and dr.enddate )
where
dr.StartDate between ''' + @StartDate + ''' and ''' + @EndDate + '''';
exec pivot_query @mySQL, 'Title', 'monyr','max(Metadata)'
go
Result:
Title Aug-10 Dec-10 Feb-11 Jan-11 Mar-11 Nov-10 Oct-10 Sep-10
-------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- --------------------
A M1 NULL NULL NULL M3 NULL M2 NULL
B NULL NULL NULL M2 NULL NULL NULL M1
C NULL M1 NULL NULL NULL NULL NULL NULL
None NULL NULL None NULL NULL None NULL NULL
这是一件更有意义的应用程序比SQL做。 做一个:
select field1, field2 from your table between date1 and date2.
然后让应用程序透视数据。 通常应用程序可以比SQL可以更有效地枢转的数据。 Espcially当列数每次改变你运行它。
它看起来像台转动时,我的意思是,列可能应该行。 这种类型的设计是非常人性化的可读性,但不是很可查询。
看看UNPIVOT运算符。 你应该能够用它来获得与您可以过滤对,然后当你做,你可以支点回到这个格式,如果需要行的数据集。
这里有一个文章: http://msdn.microsoft.com/en-us/library/ms177410.aspx
UNPIVOT通过旋转列成行执行几乎枢轴的相反的操作,。
简短的回答是否定的。 我做了一些测试。 我会给你的代码,因为NULL是如何与UNPIVOT,你将失去个月的连续范围的处理,但玩。 他们可以添加回来的支点,但这需要一个数字表,等等太多,我做了5:02! =)
WITH datepivot
AS (SELECT title,
Convert(DATETIME, Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(datecol, 'Jan', '01-01'), 'Feb', '02-01'), 'Mar', '03-01'), 'Apr', '04-01'), 'May', '05-01'), 'Jun', '06-01'), 'Jul', '07-01'), 'Aug', '08-01'), 'Sep', '09-01'), 'Oct', '10-01'), 'Nov', '11-01'), 'Dec', '12-01')) datecol,
datecol origdatecol,
Isnull(code, 0) code
FROM (SELECT title,
[Jul-10],
[Aug-10],
[Sep-10],
[Oct-10],
[Nov-10],
[Dec-10],
[Jan-11],
[Feb-11],
[Mar-11],
[Apr-11],
[May-11],
[Jun-11]
FROM test) test UNPIVOT (code FOR datecol IN ([Jul-10], [Aug-10], [Sep-10], [Oct-10], [Nov-10], [Dec-10], [Jan-11], [Feb-11], [Mar-11], [Apr-11], [May-11], [Jun-11]))AS dateunpivot)
--SELECT * from datepivot --uncomment to view unpivoted data
SELECT *
FROM (SELECT title,
code,
origdatecol
FROM datepivot
WHERE datecol BETWEEN '10-01-2010' AND '04-01-2011') a PIVOT (Max(code) FOR origdatecol IN ([Jul-10], [Aug-10], [Sep-10], [Oct-10], [Nov-10], [Dec-10], [Jan-11], [Feb-11], [Mar-11], [Apr-11], [May-11], [Jun-11])) b
您可以生成必要的SQL SELECT语句,然后使用sp_executesql的运行查询。
下面是如何产生的月份列名的例子:
DECLARE @nextMonth TABLE(
currentMonth CHAR(3),
nextMonth CHAR(3)
);
INSERT INTO @nextMonth(currentMonth, nextMonth)
SELECT 'Jan', 'Feb' UNION ALL
SELECT 'Feb', 'Mar' UNION ALL
SELECT 'Mar', 'Apr' UNION ALL
SELECT 'Apr', 'May' UNION ALL
SELECT 'May', 'Jun' UNION ALL
SELECT 'Jun', 'Jul' UNION ALL
SELECT 'Jul', 'Aug' UNION ALL
SELECT 'Aug', 'Sep' UNION ALL
SELECT 'Sep', 'Oct' UNION ALL
SELECT 'Oct', 'Nov' UNION ALL
SELECT 'Nov', 'Dec' UNION ALL
SELECT 'Dec', 'Jan'
DECLARE @start char(6), @end char(6), @current char(6), @columnNames varchar(1000)
SELECT @start = 'Oct-10', @end = 'Apr-11'
SET @current = @start;
WHILE (@current <> @end)
BEGIN
IF (@columnNames IS NULL)
SET @columnNames = @current;
ELSE
SET @columnNames = @columnNames + ', ' + @current;
SELECT @current = nextMonth + '-' + LTRIM(STR(case LEFT(@current, 3) WHEN 'Dec' THEN 1+RIGHT(@current, 2) ELSE RIGHT(@current, 2) END))
FROM @nextMonth
WHERE currentMonth = left(@current, 3)
END
SELECT @columnNames
这给了我:
Oct-10, Nov-10, Dec-10, Jan-11, Feb-11, Mar-11
递增一年可以更明确地进行。 我把自动铸造的优势。
我只能访问到SQL Server 2005,所以有可能在2008年一个更好的方法。