1

SQLクエリを参照して、日付ごとに学生の記録を要約する方法は? 念願のレポートを手に入れることができました。

現実の世界では、学生テーブルには 3,000 万のレコードがあると言われました。(StudentID, Date) にインデックスがあります。パフォーマンスを改善するための提案、またはレポートを作成するためのより良い方法はありますか?

現在、次のクエリがあります

;with cte as
(
  select id, 
    studentid,
    date,
    '#'+subject+';'+grade+';'+convert(varchar(10), date, 101) report
  from student
) 
-- insert into studentreport
select distinct 
  studentid,
  STUFF(
         (SELECT cast(t2.report as varchar(50))
          FROM cte t2
          where c.StudentId = t2.StudentId
          order by t2.date desc
          FOR XML PATH (''))
          , 1, 0, '')  AS report
from cte c;
4

1 に答える 1

1

実行計画を見なければ、最適化された SQL ステートメントを書くことは実際には不可能なので、代わりに提案を行います。

多くの場合、大容量のメモリを必要とするクエリを処理しないため、cte を使用しないでください (少なくとも、私の経験では)。代わりに、マテリアライズド/インデックス付きビューまたは作業テーブル (おそらく大きな一時テーブル) を使用して、cte データを実際のテーブルにステージングします。次に、2 番目の select (cte の後) を実行して、データを順序付きリストに結合します。

あなたの質問に対するコメントの数は、あなたが大きな問題を抱えていることを示しています。背の高いデータと細いデータ (整数、datetime2 型を考えてください) を文字列内の順序付けられたリストに変換しています。代わりに、利用可能な最小のデータ形式で保存し、後で (または決して) 文字列に操作するという観点から考えてみてください。または、「レポート」フィールドを置き換える XML データ フィールドを作成することを真剣に検討してください。

あなたがそれを機能させることができれば、これは私がすることです(インデックスのないテストケースを含む)。走行距離は異なる場合がありますが、試してみてください。

create table #student (id int not null, studentid int not null, date datetime not null, subject varchar(40), grade varchar(40))

insert into #student (id,studentid,date,subject,grade)
select 1, 1, getdate(), 'history', 'A-' union all
select 2, 1, dateadd(d,1,getdate()), 'computer science', 'b' union all
select 3, 1, dateadd(d,2,getdate()), 'art', 'q' union all
--
select 1, 2, getdate() , 'something', 'F' union all
select 2, 2, dateadd(d,1,getdate()), 'genetics', 'e' union all
select 3, 2, dateadd(d,2,getdate()), 'art', 'D+' union all
--
select 1, 3, getdate() , 'memory loss', 'A-' union all
select 2, 3, dateadd(d,1,getdate()), 'creative writing', 'A-' union all
select 3, 3, dateadd(d,2,getdate()), 'history of asia 101', 'A-'

go

select      studentid as studentid
            ,(select s2.date as '@date', s2.subject as '@subject', s2.grade as '@grade' 
            from #student s2 where s1.studentid = s2.studentid for xml path('report'), type) as 'reports'
from        (select distinct studentid from #student) s1;

ここで出力を読みやすくする方法はわかりませんが、結果セットは 2 つのフィールドです。フィールド 1 は整数、フィールド 2 はレポートごとに 1 つのノードを持つ XML です。これはまだ結果セットを送信するほど理想的ではありませんが、studentid ごとに少なくとも 1 つの結果です。

于 2013-05-08T19:08:35.717 に答える