2016-12-02 59 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(*)'? –