Как получить отчет с динамическими датами в виде столбцов в T-SQL - PullRequest
2 голосов
/ 12 января 2011

Как получить отчет с динамическими датами в виде столбцов в 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 ]

2 голосов
/ 12 января 2011

Пара комментариев к примеру в вашем вопросе.

Используйте QUOTENAME вместо того, чтобы объединять квадратные скобки самостоятельно. Это будет правильно работать с любыми ] символами в данных.

Вы, кажется, смешиваете nvarchar и varchar. Объявите динамические переменные SQL как NVARCHAR(MAX) (или NVARCHAR(4000), если он предназначен для SQL Server 2000), а не 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*/
0 голосов
/ 20 января 2011

Вот статическая версия (из коулиги):

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
...