2017-09-05 40 views
-1

我想从单行生成多行并且能够使用下面的SQL来完成它。但是我想知道是否有更好的方式来编写这个SQL,因为它很长,并且不适用于实时场景。谢谢。使用SQL将单行分割为多行使用SQL

注意: - 我的查询将返回所需的输出,但它不是一个有效的方法 来解决问题。我的实际输入有更多列,我不想写'n'没有。的SQL查询并为它们做一个UNION ALL。 请建议更好的解决方案。谢谢。

Input :- 
A.Col2 A.Col4 A.Col6 B.Col1 B.Col2 B.Col3 B.Col4 B.Col5 B.Col6 B.Col7 
    300 301 302 100 9011 100 9002 100 9002 100 
    300 301 302 101 8101  95 2001 100 2001 100 
    300 301 302 102 8101 105 2001 110 2001 110 

Desired output :- 
100 300 9011 100 
101 300 8101 95 
102 300 8101 105 
100 301 9002 100 
101 301 2001 100 
102 301 2001 110 
100 302 9002 100 
101 302 2001 100 
102 302 2001 110 

在我的例子中,我已经建立了总共10场的测试数据(前三个字段,其余七个字段。)对于第四列的每一个值我要建三行四列,三列会看起来像:

(4th column, 1st column, 5th column, 6th column), 
(4th column, 2nd column, 7th column, 8th column), 
(4th column, 3rd column, 9th column, 10th column) 

我现在的SQL:

SELECT B.Col1 AS Constructioncode, 
     A.Col2 AS OccupancyCode,  
     B.Col2 AS MappingID, 
     B.Col3 AS DamageFactor 
    FROM 
( 
SELECT 0 AS Col1,300 AS Col2,0 AS Col3,301 AS Col4,0 AS Col5,302 AS Col6, 0 AS Col7 
UNION ALL 
SELECT 100 AS Col1,9011 AS Col2,100 AS Col3,9002 AS Col4,100 AS Col5,9002 AS Col6,100 AS Col7 
UNION ALL 
SELECT 101 AS Col1,8101 AS Col2,95 AS Col3,2001 AS Col4,100 AS Col5,2001 AS Col6,100 AS Col7 
UNION ALL 
SELECT 102 AS Col1,8101 AS Col2,105 AS Col3,2001 AS Col4,110 AS Col5,2001 AS Col6,110 AS Col7 
) A 
CROSS JOIN 
(
SELECT 0 AS Col1,300 AS Col2,0 AS Col3,301 AS Col4,0 AS Col5,302 AS Col6, 0 AS Col7 
UNION ALL 
SELECT 100 AS Col1,9011 AS Col2,100 AS Col3,9002 AS Col4,100 AS Col5,9002 AS Col6,100 AS Col7 
UNION ALL 
SELECT 101 AS Col1,8101 AS Col2,95 AS Col3,2001 AS Col4,100 AS Col5,2001 AS Col6,100 AS Col7 
UNION ALL 
SELECT 102 AS Col1,8101 AS Col2,105 AS Col3,2001 AS Col4,110 AS Col5,2001 AS Col6,110 AS Col7 
) B 
WHERE B.Col1 > A.Col1 
AND A.Col1 = 0 
UNION ALL 
SELECT B.Col1 AS Constructioncode, 
     A.Col4 AS OccupancyCode,  
     B.Col4 AS MappingID, 
     B.Col5 AS DamageFactor 
    FROM 
( 
SELECT 0 AS Col1,300 AS Col2,0 AS Col3,301 AS Col4,0 AS Col5,302 AS Col6, 0 AS Col7 
UNION ALL 
SELECT 100 AS Col1,9011 AS Col2,100 AS Col3,9002 AS Col4,100 AS Col5,9002 AS Col6,100 AS Col7 
UNION ALL 
SELECT 101 AS Col1,8101 AS Col2,95 AS Col3,2001 AS Col4,100 AS Col5,2001 AS Col6,100 AS Col7 
UNION ALL 
SELECT 102 AS Col1,8101 AS Col2,105 AS Col3,2001 AS Col4,110 AS Col5,2001 AS Col6,110 AS Col7 
) A 
CROSS JOIN 
(
SELECT 0 AS Col1,300 AS Col2,0 AS Col3,301 AS Col4,0 AS Col5,302 AS Col6, 0 AS Col7 
UNION ALL 
SELECT 100 AS Col1,9011 AS Col2,100 AS Col3,9002 AS Col4,100 AS Col5,9002 AS Col6,100 AS Col7 
UNION ALL 
SELECT 101 AS Col1,8101 AS Col2,95 AS Col3,2001 AS Col4,100 AS Col5,2001 AS Col6,100 AS Col7 
UNION ALL 
SELECT 102 AS Col1,8101 AS Col2,105 AS Col3,2001 AS Col4,110 AS Col5,2001 AS Col6,110 AS Col7 
) B 
WHERE B.Col1 > A.Col1 
AND A.Col1 = 0 
UNION ALL 
SELECT B.Col1 AS Constructioncode, 
     A.Col6 AS OccupancyCode,  
     B.Col6 AS MappingID, 
     B.Col7 AS DamageFactor 
    FROM 
( 
SELECT 0 AS Col1,300 AS Col2,0 AS Col3,301 AS Col4,0 AS Col5,302 AS Col6, 0 AS Col7 
UNION ALL 
SELECT 100 AS Col1,9011 AS Col2,100 AS Col3,9002 AS Col4,100 AS Col5,9002 AS Col6,100 AS Col7 
UNION ALL 
SELECT 101 AS Col1,8101 AS Col2,95 AS Col3,2001 AS Col4,100 AS Col5,2001 AS Col6,100 AS Col7 
UNION ALL 
SELECT 102 AS Col1,8101 AS Col2,105 AS Col3,2001 AS Col4,110 AS Col5,2001 AS Col6,110 AS Col7 
) A 
CROSS JOIN 
(
SELECT 0 AS Col1,300 AS Col2,0 AS Col3,301 AS Col4,0 AS Col5,302 AS Col6, 0 AS Col7 
UNION ALL 
SELECT 100 AS Col1,9011 AS Col2,100 AS Col3,9002 AS Col4,100 AS Col5,9002 AS Col6,100 AS Col7 
UNION ALL 
SELECT 101 AS Col1,8101 AS Col2,95 AS Col3,2001 AS Col4,100 AS Col5,2001 AS Col6,100 AS Col7 
UNION ALL 
SELECT 102 AS Col1,8101 AS Col2,105 AS Col3,2001 AS Col4,110 AS Col5,2001 AS Col6,110 AS Col7 
) B 
WHERE B.Col1 > A.Col1 
AND A.Col1 = 0 
+0

在你的榜样,你硬编码的值的查询,所以很难以确定此unpivot的数据的逻辑。你如何得到10个3列的4列? – scsimon

+0

你检查了本文中引用的Pivot()SQL调用https://stackoverflow.com/a/15931734/1620112 –

+0

我的输入有10列...对于A.Col2我需要B.Col1,B.Col2, B.Col3 ... for A.Col4 I need B.Col1,B.Col4,B.Col5 ... for A.Col6 I need B.Col1,B.Col6,B.Col7。 – Teja

回答

4

下应该做的伎俩。我只用一遍就可以完成数据。

IF OBJECT_ID('tempdb..#TestData', 'U') IS NOT NULL 
DROP TABLE #TestData; 

CREATE TABLE #TestData (
    A_Col2 INT, 
    A_Col4 INT, 
    A_Col6 INT, 
    B_Col1 INT, 
    B_Col2 INT, 
    B_Col3 INT, 
    B_Col4 INT, 
    B_Col5 INT, 
    B_Col6 INT, 
    B_Col7 INT 
    ); 
INSERT #TestData (A_Col2, A_Col4, A_Col6, B_Col1, B_Col2, B_Col3, B_Col4, B_Col5, B_Col6, B_Col7) VALUES 
    (300, 301, 302, 100, 9011, 100, 9002, 100, 9002, 100), 
    (300, 301, 302, 101, 8101, 95, 2001, 100, 2001, 100), 
    (300, 301, 302, 102, 8101, 105, 2001, 110, 2001, 110); 

--==================================================================== 

SELECT 
    Constructioncode = td.B_Col1, 
    ab.OccupancyCode, 
    ab.MappingID, 
    ab.DamageFactor 
FROM 
    #TestData td 
    CROSS APPLY (VALUES 
         (td.A_Col2, td.B_Col2, td.B_Col3), 
         (td.A_Col4, td.B_Col4, td.B_Col5), 
         (td.A_Col6, td.B_Col6, td.B_Col7) 
        ) ab (OccupancyCode, MappingID, DamageFactor) 
ORDER BY 
    ab.OccupancyCode, 
    td.B_Col1; 

结果...

Constructioncode OccupancyCode MappingID DamageFactor 
---------------- ------------- ----------- ------------ 
100    300   9011  100 
101    300   8101  95 
102    300   8101  105 
100    301   9002  100 
101    301   2001  100 
102    301   2001  110 
100    302   9002  100 
101    302   2001  100 
102    302   2001  110