SQL Server - 从另一个表设置多个列

时间:2013-06-27 20:28:04

标签: sql sql-server

我有两张桌子。

表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个类别。他们是这样做的吗?我正在努力想出一个查询。

5 个答案:

答案 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

如果我们接受第二次查询,则表示您希望IDCategory的所有可能组合,以及该组合是否出现在Table2中的布尔值(使用Code }回到ID中的Table1

由于似乎没有IDCategory的规范列表,我们会生成它:

CREATE VIEW v_AllCategories AS
   SELECT DISTINCT ID, Category FROM v_Table1 CROSS JOIN Table2

获取代表IDCategory的列表非常简单:

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    

从那里开始,您需要PIVOTCategory值作为列:

SELECT
    ID,
    cat1,
    cat2,
    cat3
FROM v_CategoryReports
PIVOT (
    MAX([Reported]) FOR Category IN ([cat1], [cat2], [cat3])
) p

既然你提到超过50个'类别',我会假设它们不是'cat1' - 'cat50'。在这种情况下,您需要对透视操作进行编码。

SqlFiddle with a self-contained example.

答案 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