我有两张桌子。
表1
ID Code1 Code2 Code3
10 1.1 1.2 1.3
表2
Code Group Category
1.1 a cat1
1.2 b cat1
1.3 c cat2
1.4 d cat3
现在我需要从这两个表格中获得两种不同形式的输出
输出1
ID Group1 Group2 Group3
10 a b c
输出2
ID cat1 cat2 cat3
10 1 1 0
这里cat1,cat2,cat3列本质上是布尔值,因为表1没有任何与cat3相对应的代码,所以这个值为0。
我正在考虑使用case语句执行此操作,但是大约有1000个代码映射到大约50个类别。他们是这样做的吗?我正在努力想出一个查询。
答案 0 :(得分:0)
这些答案假设表2中提供了所有3个代码。如果没有,则应使用OUTER连接而不是INNER。
输出1可以像这样实现:
select t1.ID,
cd1.Group as Group1,
cd2.Group as Group2,
cd3.Group as Group3
from table1 t1
inner join table2 cd1
on t1.Code1 = cd1.Code
inner join table2 cd2
on t1.Code2 = cd2.Code
inner join table2 cd3
on t1.Code3 = cd3.Code
输出2比较棘手。由于您希望Table2中的每一行都有一列,您可以编写编写SQL的SQL。
基本上从这个基本陈述开始:
select t1.ID,
//THE BELOW WILL BE GENERATED ONCE PER ROW
Case when cd1.Category = '' OR
cd2.Category = '' OR
cd3.Category = '' then convert(bit,1) else 0 end as '',
//END GENERATED CODE
from table1 t1
inner join table2 cd1
on t1.Code1 = cd1.Code
inner join table2 cd2
on t1.Code2 = cd2.Code
inner join table2 cd3
on t1.Code3 = cd3.Code
然后你可以像这样在中间生成代码:
select distinct 'Case when cd1.Category = '''+t2.Category+''' OR
cd2.Category = '''+t2.Category+''' OR
cd3.Category = '''+t2.Category+''' then convert(bit,1) else 0 end as ['+t2.Category+'],'
from table2 t2
将这些结果粘贴到原始SQL语句中(去掉尾随的逗号),你应该好好去。
答案 1 :(得分:0)
首先,我强烈建议你研究另一种选择。这将非常快速地混乱,因为您实际上将行视为列。 Table1
已经非规范化并没有多大帮助 - 尽管如果它实际上只有3列,那么将它再次标准化并不是那么重要。:
CREATE VIEW v_Table1 AS
SELECT Id, Code1 as Code FROM Table1
UNION SELECT Id, Code2 as Code FROM Table1
UNION SELECT Id, Code3 as Code FROM Table1
如果我们接受第二次查询,则表示您希望ID
和Category
的所有可能组合,以及该组合是否出现在Table2
中的布尔值(使用Code
}回到ID
中的Table1
。
由于似乎没有ID
和Category
的规范列表,我们会生成它:
CREATE VIEW v_AllCategories AS
SELECT DISTINCT ID, Category FROM v_Table1 CROSS JOIN Table2
获取代表ID
和Category
的列表非常简单:
CREATE VIEW v_ReportedCategories AS
SELECT DISTINCT ID, Category FROM Table2
JOIN v_Table1 ON Table2.Code = v_Table1.Code
把它们放在一起,然后我们可以让bool告诉我们哪个存在:
CREATE VIEW v_CategoryReports AS
SELECT
T1.ID, T1.Category, CASE WHEN T2.ID IS NULL THEN 0 ELSE 1 END as Reported
FROM v_AllCategories as T1
LEFT OUTER JOIN v_ReportedCategories as T2 ON
T1.ID = T2.ID
AND T1.Category = T2.Category
以正常的形式为您提供答案:
ID | Category | Reported
10 | cat1 | 1
10 | cat2 | 1
10 | cat3 | 0
从那里开始,您需要PIVOT
将Category
值作为列:
SELECT
ID,
cat1,
cat2,
cat3
FROM v_CategoryReports
PIVOT (
MAX([Reported]) FOR Category IN ([cat1], [cat2], [cat3])
) p
既然你提到超过50个'类别',我会假设它们不是'cat1' - 'cat50'。在这种情况下,您需要对透视操作进行编码。
答案 2 :(得分:0)
我们可以使用Pivot功能并动态构建查询。一些如下所示:
查询1
Select * from
(SELECT Id, Code, GroupCode
FROM Table2 join Table1
ON Table1.Code1 = Table2.Code
OR Table1.Code2 = Table2.Code
OR Table1.Code3 = Table2.Code
) ps
PIVOT
(
Max (GroupCode)
FOR Code IN
( [1.1], [1.2], [1.3])
) AS Result
查询2
Select * from
(SELECT Id, GroupCode, Category
FROM Table2 join Table1
ON Table1.Code1 = Table2.Code
OR Table1.Code2 = Table2.Code
OR Table1.Code3 = Table2.Code
) ps
PIVOT
(
Count (GroupCode)
FOR Category IN
( [cat1], [cat2], [cat3])
) AS Result
答案 3 :(得分:-1)
MSSQL中的PIVOT和CROSS APPLY关键字可以帮助你。虽然目前还不清楚你想要完成什么。 CROSS应用于在相关子查询上执行连接并为每个连接显示不同的输出,以及PIVOT用于对数据执行交叉表。
对于表1,如果将它们混合成更标准化的样式可能会更容易。
WITH cteTab1 (Id, Code) AS
(
SELECT Id, Code1 FROM Table1
UNION ALL
SELECT Id, Code2 FROM Table1
UNION ALL
SELECT Id, Code3 FROM Table1)
SELECT *
FROM Table2 INNER JOIN cteTab1 ON Table2.Code = cteTab1.Code
答案 4 :(得分:-1)
不幸的是,你坚持使用Table1的糟糕设计。更好的方法是为ID 10设置3行。
但是,根据您当前的设计,您的查询将如下所示:
SELECT ID, G1.Group Group1, G2.Group Group2, G3.Group Group3
FROM Table1 T1
INNER JOIN Table2 G1 ON T1.Code1 = G1.Code
INNER JOIN Table2 G2 ON T1.Code2 = G2.Code
INNER JOIN Table2 G3 ON T1.Code3 = G3.Code
和
SELECT ID, G1.Category Cat1, G2.Category Cat2, G3.Category Cat3
FROM Table1 T1
INNER JOIN Table2 G1 ON T1.Code1 = G1.Code
INNER JOIN Table2 G2 ON T1.Code2 = G2.Code
INNER JOIN Table2 G3 ON T1.Code3 = G3.Code