2016-12-02 4 views
3

漠然としたタイトルに対する謝罪ですが、これは直接的な回答を探すよりもアドバイスが必要です。参考までに、私はSSMS 2014を使用しています。厄介な記憶データのクエリ

私は作成していないデータベースで作業していますが、私は現在の形式でデータを扱うのに苦労しています。私は以下の表の例を挙げました。

+-----+----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ 
|DtID | ID | Mo1 | Mo2 | Tu1 | Tu2 | We1 | We2 | Th1 | Th2 | Fr1 | Fr2 | 
+-----+----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ 
| 565 | 12 | 0 | 1 | 0 | 1 | 1 | 0 | 0 | 0 | 1 | 0 | 
| 565 | 13 | 0 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 
| 565 | 14 | 0 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 
| 565 | 15 | 1 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 
| 572 | 12 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 
| 572 | 13 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 1 | 
| 572 | 14 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 
| 572 | 15 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 
+-----+----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ 

DTID

は、日付識別子を開始一週間で、IDは、人識別子である、MO1等月曜日AM、月曜日のMo2 PMは、1人がそのセッションに出席した意味を表します。テーブルが600k行を超えています。

特定の日付範囲の間でデータを照会しようとしたときに問題が発生します。たとえば、日付の識別子566と575の間に現在の出席マークの合計を求めたいとします。566は565から始まる火曜日を表し、 575は、572から始まる週の木曜日を指します。

私は、以下の形式で書式設定されたテーブル(例:1行目)を使用した方がはるかに快適です。

+-----+----+------+---------+ 
|DtID | ID | AMPM | Present | 
+-----+----+------+---------+ 
| 565 | 12 | 1 |  0 | 
| 565 | 12 | 2 |  1 | 
| 566 | 12 | 1 |  0 | 
| 566 | 12 | 2 |  1 | 
| 567 | 12 | 1 |  1 | 
| 567 | 12 | 2 |  0 | 
| 568 | 12 | 1 |  0 | 
| 568 | 12 | 2 |  0 | 
| 569 | 12 | 1 |  1 | 
| 569 | 12 | 2 |  0 | 
+-----+----+------+---------+ 

これは可能ですか?データをそのままクエリする有効な方法はありますか?私はかなりSQLに慣れていて、これまでのほとんどすべての学習はこのサイトの質問と回答を解釈してきたものです。私が言うように、私は私が探しているものに対する答えを本当に知っていないので、ここのユーザーの集団的な助言と知恵は私にとって非常に役に立つでしょう。

多くのありがとうございます。

+0

あなたが正しいです。第2の表現は、第1の表現よりもはるかに意味があります。私は既存のテーブルデザインに欠陥があると主張しますが、私たちが持っているものと一緒に作業しなければなりません。必要な形式で入手するにはいくつかの方法があります。別のテーブルに参加して1行を10にすることができます(これはあなたが望むものです) - ここに例があります:http://stackoverflow.com/questions/40866952/merge-start-and-end-columns-to-one -column/40867201#40867201。あなたは10人のすべてのユナイテッドを使うことができますが、一般に、クエリプランナーが最適化するのは難しいです。 –

+0

多くの作業がありますが、データベース設計が一貫してこの「厄介な」ものであり、多くのレポートを行う必要がある場合は、データウェアハウスを構築できます –

+0

2番目の設計に欠陥があると考えています。本当に平日の表現はありません。並べ替えの基準がないため、2番目の表の行が参照する日を指定することはできません。 –

答えて

2

私は、私はあなたが私がデータを再構築するためにハードにプッシュなりました場合は、その日の情報

select DtID,ID,left(day,2) as day,right(day,1) as AMPM,Present 

from t unpivot (Present for day in (Mo1,Mo2,Tu1,Tu2,We1,We2,Th1,Th2,Fr1,Fr2)) t 

+------+----+-----+------+---------+ 
| DtID | ID | day | AMPM | Present | 
+------+----+-----+------+---------+ 
| 565 | 12 | Mo | 1 | 0  | 
+------+----+-----+------+---------+ 
| 565 | 12 | Mo | 2 | 1  | 
+------+----+-----+------+---------+ 
| 565 | 12 | Tu | 1 | 0  | 
+------+----+-----+------+---------+ 
| 565 | 12 | Tu | 2 | 1  | 
+------+----+-----+------+---------+ 
| 565 | 12 | We | 1 | 1  | 
+------+----+-----+------+---------+ 
| 565 | 12 | We | 2 | 0  | 
+------+----+-----+------+---------+ 
| 565 | 12 | Th | 1 | 0  | 
+------+----+-----+------+---------+ 
| 565 | 12 | Th | 2 | 0  | 
+------+----+-----+------+---------+ 
| 565 | 12 | Fr | 1 | 1  | 
+------+----+-----+------+---------+ 
| 565 | 12 | Fr | 2 | 0  | 
+------+----+-----+------+---------+ 
| 565 | 13 | Mo | 1 | 0  | 
+------+----+-----+------+---------+ 
| 565 | 13 | Mo | 2 | 0  | 
+------+----+-----+------+---------+ 
| 565 | 13 | Tu | 1 | 1  | 
+------+----+-----+------+---------+ 
| 565 | 13 | Tu | 2 | 1  | 
+------+----+-----+------+---------+ 
| 565 | 13 | We | 1 | 1  | 
+------+----+-----+------+---------+ 
| 565 | 13 | We | 2 | 1  | 
+------+----+-----+------+---------+ 
| 565 | 13 | Th | 1 | 0  | 
+------+----+-----+------+---------+ 
| 565 | 13 | Th | 2 | 0  | 
+------+----+-----+------+---------+ 
| 565 | 13 | Fr | 1 | 0  | 
+------+----+-----+------+---------+ 
| 565 | 13 | Fr | 2 | 0  | 
+------+----+-----+------+---------+ 
+0

これはちょうど私の目的のためにそこにあり、私は私の解決策を見つけるためにこれを使用することができます。あなたが私の「好きな」代替案に気付いた場合、日付情報はその日に基づいて増分されるため、その日の情報は失われません。たとえば、火曜日は566で表されます。 – Necessary

+0

私は「優先」の部分を得ていません –

+0

私は、私がより快適に使うことができるオリジナルのポストの表を参考にしていました。私のデータセットの実際の列見出しは、この例では「MoAM」、「TuAM」などと呼ばれている「RegIdentAM1」「RegIdentAM2」などと呼ばれています。私はちょうど1日のidentを抜け出すために正しい関数を使い、これを日付識別子に加え、正しい日付を返すものを引いたものです。あなたの返信にはとても満足しています - 私は以前にピストピボットに出くわしていなかったので、今私の処分でこれを持っていることを嬉しく思っています。 – Necessary

1

を失うしたいとは思いません。私が本番システムでこれを行うことができる1つの方法は、名前の変更の仕掛けを使うことです。最初に新しい表を作成し、元の表の名前を付けたビューを作成します。既存のレポートとクエリは、パフォーマンス要件に基づいて置き換えられるまで機能します。

一方で、unpivotやjoinのようなもっと使いやすいものを使うことができましたが、私はいつも設定、保守、パフォーマンス上の問題がない組合解を見つけました。結果は異なるかもしれませんが、テストは簡単です。

編集: データを何度も繰り返して追加して作成した20,971,520行のデータセットで、いくつかのテストを実行しました(Temp Insert * From Temp)。

Select * From vTemp - 1:28 

Select DtID,ID,col,Present 
    From Temp UnPivot (Present For Col In (Mo1,Mo2,Tu1,Tu2,We1,We2,Th1,Th2,Fr1,Fr2)) T - 1:30  

Select * From vTemp Where ID = 12 - :23 

Select DtID,ID,col,Present 
    From Temp UnPivot (Present For Col In (Mo1,Mo2,Tu1,Tu2,We1,We2,Th1,Th2,Fr1,Fr2)) T 
Where ID = 12 :24 

要するに、ピボットが好きな人は入力がはるかに少ないです。ピボットの構文が気に入らない人は、重複を削除するかどうかによって、UnionまたはUnion Allを使用できます。例えば

Drop Table Temp 
Create Table Temp (DtID int, ID int, Mo1 bit, Mo2 bit, Tu1 bit, Tu2 bit, We1 bit, We2 bit, Th1 bit, Th2 bit, Fr1 bit, Fr2 bit) 


Insert Temp Values (565 , 12 , 0 , 1 , 0 , 1 , 1 , 0 , 0 , 0 , 1 , 0) 
Insert Temp Values (565 , 13 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0) 
Insert Temp Values (565 , 14 , 0 , 1 , 1 , 1 , 0 , 0 , 1 , 1 , 1 , 0) 
Insert Temp Values (565 , 15 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 1) 
Insert Temp Values (572 , 12 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0) 
Insert Temp Values (572 , 13 , 1 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 1) 
Insert Temp Values (572 , 14 , 0 , 0 , 1 , 0 , 0 , 0 , 1 , 1 , 0 , 0) 
Insert Temp Values (572 , 15 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0) 

Drop View vTemp 
Go 
Create View vTemp As 
Select DtID, ID, 'Monday' Day, 1 AmPm, Mo1 Present From Temp 
Union All 
Select DtID, ID, 'Monday' Day, 2 AmPm, Mo1 Present From Temp 
Union All 
Select DtID, ID, 'Tuesday' Day, 1 AmPm, Tu1 Present From Temp 
Union All 
Select DtID, ID, 'Tuesday' Day, 2 AmPm, Tu2 Present From Temp 
Union All 
Select DtID, ID, 'Wednesday' Day, 1 AmPm, We1 Present From Temp 
Union All 
Select DtID, ID, 'Wednesday' Day, 2 AmPm, We2 Present From Temp 
Union All 
Select DtID, ID, 'Thursday' Day, 1 AmPm, Th1 Present From Temp 
Union All 
Select DtID, ID, 'Thursday' Day, 2 AmPm, Th2 Present From Temp 
Union All 
Select DtID, ID, 'Friday' Day, 1 AmPm, Fr1 Present From Temp 
Union All 
Select DtID, ID, 'Friday' Day, 2 AmPm, Fr2 Present From Temp 

Go 

Select * From vTemp Order By ID, DtID, Day, AmPm 
+0

ビューに挿入すると機能しません。 –

+0

彼はDMLではないクエリについて話していました。私が強くお勧めするベースデザインを変更することなく、自分が望むやり方でデータを表現し、インサートを行う方法を知りません。 –

+0

パフォーマンステストですか? (1)あなたはそれを何回繰り返しましたか? (2)実行する前にキャッシュをきれいにしておきましたか? (3)あなたはサーバー時間かクライアント時間かかりましたか? 'select *'を 'select count(*)'に変更する方法は? –