2011-01-12 3 views
2

動的日付をT-SQLの列として使用してレポートを取得する方法。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) 
+0

に問題があるように思われる何あなたの例? – Lamak

+0

実際には問題はありませんが、そのようなスクリプトの例を得るのは苦労しました。私はそれが他の誰かを片付けることを願っています。私は共有するのが好きです。 :) –

答えて

2

あなたの質問の例に関するいくつかのコメント。

角括弧を連結するのではなく、QUOTENAMEを使用してください。これにより、データ内の任意の]文字が正しく処理されます。

nvarcharvarcharと混ざっているようです。 NVARCHAR(MAX)(またはSQL Server 2000を対象とする場合はNVARCHAR(4000))という動的SQL変数を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

返事をありがとう。私はそれを考慮に入れます。 しかし、私は直接UserInputではなく、検証されたDateTimeフィールドを使用します。 –

+0

@Meltdown - 他の人がこのコードに遭遇する可能性があります(あなたが投稿した理由です)。 –

0

ここでは、(coleagueから)静的なバージョンです:

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 
関連する問題