我有一种情况,我必须生成一系列日期(比如开始日期和结束日期)。 现在我想在这些生成日期填写特定日期的记录。
;WITH DateRange AS
(
SELECT @start_date DateValue
UNION ALL
SELECT DateValue + 1
FROM DateRange
WHERE DateValue + 1 <= @end_date
)
如果@start_date = '2013-01-01' and @end_date= '2013-01-05'
生成的日期为'01/01/2013,01/02/2013,01/03/2013,01/04/2013,01/05/2013'
现在我想转动它以填充特定日期的特定数据。 我怎样才能做到这一点?
修改 我有3列,即Duration,StartDate和EndDate。现在我想动态生成这些日期并按时填充持续时间的值。
例如:if Duration = 6
和@start_date = '2013-01-01' and @end_date= '2013-01-05'
我想生成一个持续时间等于6的日期列表。
更新2:
如果你不明白我的问题,请详细说明。
要求输出
如果@startDate='2013-01-01'
和@endDate='2013-01-07'
,则输出必须如下:
**
**
更新3:
答案 0 :(得分:3)
[更新2013-12-18 11:22 UTC]
[更新2013-12-18 14:19 UTC]
[更新2013-12-19 11:11 UTC]
因为我不知道您正在使用的表的名称,所以我创建了一个名为yeahyeah
的名称。你应该用你自己的表的名称替换它。我已插入您提到的值(从问题中显示的日期持续时间)。
程序应如下所示。我称之为pivotit
。
create procedure pivotit (@start_date date, @end_date date)
as
/*
step 1:
identify all the data you need to fill the pivoted table.
this is achieved by using your daterange generator and joining
it with your table. the result is kept in a dynamic table
*/
declare @acols table (i int, d date, l int);
;WITH DateRange AS
(
SELECT @start_date DateValue
UNION ALL
SELECT dateadd(dd,1,DateValue)
FROM DateRange
WHERE dateadd(dd,1,DateValue) <= @end_date
)
insert into @acols (i, d, l)
select id, DateValue, Duration from DateRange
join yeahyeah on ( DateRange.DateValue >= yeahyeah.FromDate
and DateRange.DateValue <= yeahyeah.ToDate);
/*
step 2:
for pivot you need all the columns that will be adressed. so
we create a string with all the distinct dates from the dynamic
table. these will then be put into a format like [1], [2], [3], ...
to create a dynamic select.
*/
declare @p varchar(max) = '';
declare @s varchar(max);
select @p = @p + ', [' + CONVERT(varchar,d) + ']' from (select distinct d from @acols) a;
set @p = SUBSTRING(@p,3,len(@p)-2);
/*
step 3:
create the dynamic select.
alas neither the dynamic table nor the parameters are available from
inside the dynamic sql. i might try to use bind variables, but was
not 100% sure if that would work here. so put in the declares for start_
and end_date from the procedure parameters and build up the dynamic table
once more.
then i use @p for the pivoted select. this is done by selecting the column
for the rows (id) and all the values from the pivot as columns (@p).
details on the whole pivot thing are here:
http://technet.microsoft.com/en-us/library/ms177410(v=sql.105).aspx
basically you tell sql-server (explicitly) what you want as the columns (@p),
what rows you want (id) and how to aggregate the values in the intersections
(sum(l))
[update 2013-12-19]
i added a routine that makes a cartesian product that has all the combination
of dates and ids in @acols, finds the ones that are missing in @acols and inserts
them with duration 0. then the pivoted cells are complete and display the zero
instead of NULL. you cannot use isnull or coalesce here since not the value
of the cell is NULL, the intersection simply did not exist.
*/
set @s = '
declare @start_date date = convert(date,'''+CONVERT(varchar,@start_date,112)+''',112);
declare @end_date date = convert(date,'''+CONVERT(varchar,@end_date,112)+''',112);
declare @acols table (i int, d date, l int);
;WITH DateRange AS
(
SELECT @start_date DateValue
UNION ALL
SELECT dateadd(dd,1,DateValue)
FROM DateRange
WHERE dateadd(dd,1,DateValue) <= @end_date
)
insert into @acols (i, d, l)
select id, DateValue, Duration from DateRange
join yeahyeah on ( DateRange.DateValue >= yeahyeah.FromDate
and DateRange.DateValue <= yeahyeah.ToDate);
with cart as
(
select distinct
a.i
, b.d
from @acols a
join @acols b
on 1=1
)
insert into @acols (i, d, l)
select cart.i
, cart.d
, 0
from cart
left outer join
@acols a
on cart.i = a.i
and cart.d = a.d
where a.i is null;
select id, '+@p+'
from
( select convert(varchar,d) as d
, l
, i as id
from @acols ) as sourcetable
pivot (
sum(l)
for d in ('+@p+')
) as pivottable';
execute(@s);
创建程序后,您可以执行以下操作:
exec pivotit @start_date = '2013-01-01', @end_date = '2013-01-31'
然后会产生:
答案 1 :(得分:0)
您可以编写如下查询:
declare @start_date datetime,@end_date datetime ;
set @start_date ='2013-01-01' ;
set @end_date = '2013-01-05' ;
DECLARE @columns NVARCHAR(MAX),@sql NVARCHAR(MAX);
SET @columns = N'';
WITH DateRange AS
(
SELECT @start_date DateValue
UNION ALL
SELECT DateValue + 1
FROM DateRange
WHERE DateValue + 1 <= @end_date
)
--Get column names for entire pivoting
SELECT @columns += N', ' + QUOTENAME(SpreadCol)
FROM (select distinct convert(varchar(10),DateValue,101) as SpreadCol
from DateRange
) AS T;
PRINT @columns;
然后在动态数据透视查询中使用@columns作为扩展列。
答案 2 :(得分:0)
使用SQL Server Reporting Services向导。
如果需要定期生成报告,可以将其发布到报告服务器上。用户可以导出为首选格式。它看起来也不错;)
如果您愿意,也可以绘制结果图表。
有关报告向导的详细信息,请参阅http://technet.microsoft.com/en-us/library/ms160326(v=sql.105).aspx。
有关生成日期范围表的其他方法,请参阅SQL query to select dates between two dates。
答案 3 :(得分:-1)
我的查询 - 日期范围可以是多长。如果你在页面中显示的方式很长。首先用其他样本数据然后将其转换为动态sql或者询问。
Declare @startDate date='2013-01-01'
Declare @endDate date='2013-01-07'
Declare @t table(startdate date,enddate date,duration int)
insert into @t values('2013-01-01','2013-01-03',15),('2013-01-04','2013-01-06',10)
;WITH DateRange AS
(
SELECT @startDate DateValue
UNION ALL
SELECT dateadd(day,1,DateValue)
FROM DateRange
WHERE dateadd(day,1,DateValue) < @endDate
)
select [2013-01-01],[2013-01-02],[2013-01-03],[2013-01-04],[2013-01-05],[2013-01-06]
from
(select a.datevalue, duration from DateRange a
left join @t b on a.DateValue >= b.startdate and a.DateValue<= b.enddate)AS SourceTable
PIVOT
(
Min(duration) for datevalue in([2013-01-01],[2013-01-02],[2013-01-03],[2013-01-04],[2013-01-05],[2013-01-06])
) AS PivotTable