首页 > 解决方案 > 在 SQL 中查询一个杂乱的表

问题描述

我可以使用一些帮助来编写一个查询,它将我遇到的最奇怪的表之一变成有用的东西。所以它开始了.. 这是一个 SQL 表(我们称之为“THRESHOLDS”),显示阈值的每周配置文件。看起来像:

Column 1, 'Product' = X
Column 2, 'Monday_AM' = 0-2;1-2;2-2;3-2;4-2;5-2;6-2;7-2;8-2;9-2;10-2;11-2
Column 3, 'Monday_PM' = 0-2;1-2;2-2;3-2;4-2;5-2;6-2;7-2;8-2;9-2;10-2;11-2
...
Column 15, 'Sunday_PM' = 0-2;1-2;2-2;3-2;4-2;5-2;6-2;7-2;8-2;9-2;10-2;11-2

如您所见,有 14 列带有阈值,每半天一列。在行上,我们有从(比方说)A 到 Z 的产品,每天和每小时都有不同的阈值。

我想要的(基于上面的例子)是:

Product     Day     Hour    Threshold
X           1       0       2
X           1       1       2
X           1       2       2
X           1       3       2
X           1       4       2
X           1       5       2
X           1       6       2
X           1       7       2
X           1       8       2
X           1       9       2
X           1       10      2
X           1       11      2
X           1       12      2
X           1       13      2
X           1       14      2
X           1       15      2
X           1       16      2
X           1       17      2
X           1       18      2
X           1       19      2
X           1       20      2
X           1       21      2
X           1       22      2
X           1       23      2
X           2       0       2
X           2       1       2
X           2       2       2
X           2       3       2
etc…

有什么方便的技巧可以用于这种类型的转换吗?我正在挣扎!

感谢您的关注。:)

标签: sqlsql-serverdelimitertranspose

解决方案


您可以使用 unpivotcross apply然后使用string_split()和一些字符串操作:

select t.product, v.day,
       (left(s.value, charindex('-', s.value) - 1)  + v.offset) as hour,
       stuff(s.value, 1, charindex('-', s.value), '')
from t cross apply
     (values (t.monday_am, 1, 0), 
             (t.monday_pm, 1, 12),
             (t.tuesday_am, 2, 0),
             . . .
     ) v(str, day, offset)
     string_split(v.str, ';') s

是一个 db<>fiddle。


推荐阅读