2016-12-02 70 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代表週一上午,MO2週一下午,等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

你說得對。第二種表示比第一種更有意義。我會爭辯說,現有的桌子設計是有缺陷的,但是我們必須與我們所得到的一起工作。有許多方法可以以所需的形式獲得它。你可以交叉連接到另一個表將1行變成10(這是你想要的) - 這裏是一個例子:http://stackoverflow.com/questions/40866952/merge-start-and-end-columns-to-one -column/40867201#40867201。您可以全部使用10個「聯合」,但查詢規劃人員通常難以對其進行優化。 –

+0

儘管做了很多工作,但如果數據庫設計始終如此「尷尬」,並且您必須進行大量報告,則可以構建數據倉庫 –

+0

我認爲第二個設計也有缺陷,因爲它使得真的沒有工作日的代表。由於沒有其他標準可以進行排序,所以不可能確定第二個表格中的哪一天指的是哪一天。 –

回答

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

通過首選,我指的是原始帖子中的表格,我感覺更舒適。我的數據集的實際列標題被稱爲'RegIdentAM1''RegIdentAM2'等,在這個例子中我稱之爲'MoAM','TuAM'等。我剛剛使用了正確的函數來查看日期標識,並將其添加到日期標識中,並減去返回正確日期的日期標識。非常滿意你的回覆 - 我以前沒有遇到過轉輪,所以我很高興現在可以隨時使用。插入到視圖中不起作用 – Necessary

1

如果我是你,我會努力推進重組的數據。我在生產系統中能夠做到這一點的一種方法是使用重命名技巧。首先創建一個新表,然後創建一個名爲原始表命名方式的視圖。現有的報告和查詢將仍然有效,直到根據性能要求進行替換。

與此同時,您可以使用更多幻想像unpivot或加入,但我總是發現一個工會解決方案是簡單的設置,維護和從未有過性能問題。你可能會有不同的結果,但它很容易測試。

編輯: 我對通過重複附加數據(插入溫度選擇*從溫度)創建的20,971,520行數據集運行了一些測試。

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(*)'? –