如何使用动态日期作为T-SQL中的列获取报表

时间:2011-01-12 11:32:47

标签: sql-server tsql pivot

如何将包含动态日期的报告作为T-SQL中的列。

我正在寻找像这样疯狂的代码。

希望它能帮助其他人。

如果有人知道更好的解决方案,请发帖。

DECLARE @columns VARCHAR(8000)

SELECT @columns = COALESCE(@columns + ',[' + convert(nvarchar(12), data, 103) + ']',
'[' + convert(nvarchar(12), data, 103)+ ']')
FROM Item
GROUP BY data
--print @columns


DECLARE @query VARCHAR(8000)

SET @query = '

;WITH G1 As
(
select id_item, convert(nvarchar(12), data, 103) as data, COUNT(*) as numar
from Item
group by id_item, data

)

SELECT *
FROM G1
PIVOT
(
sum(numar)
FOR [data]
IN (' + @columns + ')
) AS G2
'
print @query
EXECUTE(@query)

2 个答案:

答案 0 :(得分:2)

对你问题中的例子做了几点评论。

使用QUOTENAME而不是自己连接方括号。这将正确处理数据中的任何]个字符。

您似乎在混合nvarcharvarchar。将动态SQL变量声明为NVARCHAR(MAX)(如果定位SQL Server 2000,则为NVARCHAR(4000))而不是VARCHAR(8000)。这意味着您的查询可以正确使用Unicode数据,并且在连接动态SQL时通常更安全。

(只是添加一个我为什么说这更安全的例子)

create table #t (a int, b char(1));

DECLARE @querystring varchar(max)
DECLARE @nquerystring nvarchar(max)
DECLARE @userinput nvarchar(100) = N'ʼ;Drop Table #t--'

IF @userinput LIKE '%''%'
        BEGIN
        RAISERROR('Possible SQL injection',16,1)
        RETURN
        END


SET @nquerystring = 'select * from #t where b = ''' + @userinput + ''''


exec (@nquerystring)

select OBJECT_ID('tempdb..#t') /*NOT NULL, Still There*/

SET @querystring = @nquerystring /*ʼ nchar(700) gets silently converted to a regular ' character*/

exec (@querystring)

select OBJECT_ID('tempdb..#t') /*NULL, Table Dropped*/

答案 1 :(得分:0)

这是一个静态版本(来自同事):

with c as (
    select
        p.id_doc,
        p.id_usr,
        DATEDIFF(DAY, p.created_at, getdate()) as date_diff
    from Document p
    where 1 = 1 
), p as (
    select
        pvt.id_usr,
        [0], [1], [2], [3], [4], [5], [6], [7], [8], [9]
    from c
    PIVOT (COUNT(c.id_doc) FOR c.date_diff IN ([0], [1], [2], [3], [4], [5], [6], [7], [8], [9])) AS pvt
)
select
    u.username,
    u.name,
    [0], [1], [2], [3], [4], [5], [6], [7], [8], [9],
    y.nr,
    y.total_money
from p
inner join Users u on u.id_usr = p.id_usr
cross apply (
    select
        COUNT(1) as nr,
        SUM(premium) as total_money
    from Document z
    where z.id_usr = p.id_usr
) as y
order by nr desc