SQL - 在所有可能的唯一排列中将多个列组合成1个字符串

时间:2014-09-15 19:13:27

标签: sql sql-server sql-server-2012 permutation

我有下表:

AddressId     SubBuildingName    BuildingName    BuildingNumber   Postcode
12345         Flat 1             SomeBuilding    80               MK34 1PU
12346         Flat 2             SomeBuilding    80               MK34 1PU
12347         Flat 7             OtherBuilding   NULL             MK22 9IT

对于每个地址,我需要将 SubBuildingName,BuildingName和BuildingNumber 组合成所有可能的非重复排列中的1个逗号分隔字符串,如下所示:

AddressId     AddressLine1
12345         Flat 1, SomeBuilding, 80
12345         Flat 1, 80, SomeBuilding 
12345         80, Flat 1, SomeBuilding
12345         80, SomeBuilding, Flat 1
12345         SomeBuilding, Flat 1, 80
12345         SomeBuilding, 80, Flat 1
12346         Flat 1, SomeBuilding, 80
12346         Flat 1, 80, SomeBuilding 
12346         80, Flat 1, SomeBuilding
12346         80, SomeBuilding, Flat 1
12346         SomeBuilding, Flat 1, 80
12346         SomeBuilding, 80, Flat 1
12347         Flat 7, OtherBuilding
12347         OtherBuilding, Flat 7

2 个答案:

答案 0 :(得分:2)

如果您提前知道要使用哪些列,则可以使用UNPIVOT和多个自连接来实现所有排列效果,而无需编写二十四个语句,例如以下内容:

DECLARE @Permutations TABLE (ID INT IDENTITY(1,1), v1 VARCHAR(10), v2 VARCHAR(10), v3 VARCHAR(10), v4 VARCHAR(10))

INSERT INTO @Permutations (v1, v2, v3, v4) VALUES ('a', 'b', 'c', 'd')
INSERT INTO @Permutations (v1, v2, v3, v4) VALUES ('w', 'x', 'y', 'z');

WITH alldata AS (
SELECT ID, Value, ValName 
FROM 
    @Permutations
UNPIVOT 
 (Value FOR ValName IN (v1, v2, v3, v4)) up
)

SELECT 
    one.ID AS AddressID, 
    one.Value + ',' + two.Value + ',' + three.Value + ',' + four.Value AS AddressLine1
FROM 
    alldata one
     INNER JOIN 
    alldata two ON 
        one.ID = two.ID AND 
        one.ValName <> two.ValName
     INNER JOIN 
    alldata three ON 
        one.ID = three.ID AND
        one.ValName <> three.ValName AND
        two.ValName <> three.ValName 
     INNER JOIN 
    alldata four ON 
        one.ID = four.ID AND
        one.ValName <> four.ValName AND
        two.ValName <> four.ValName AND
        three.ValName <> four.ValName
ORDER BY AddressID, AddressLine1 
编辑:阅读自从我开始编写代码以来发表的评论,我不清楚OP是否会满足于看到这样的代码(四个列的四个语句而不是二十四个UNION,五个用于五,等)或需要整个事物是动态的。如果您正在寻找一种编写最小代码而不需要手动计算每种可能排列的技术,那么这个答案就会满足。

答案 1 :(得分:1)

通过它的本质联盟将做一个独特的。 Coalesce用于处理空值 每个语句处理6个不同的潜在订单

SELECT AddressId, 
       CONCAT(coalesce(SubBuildingName,''), ', ',
              coalesce(BuildingName,''), ', ',
              coalesce(BuildingNumber,'')
       ) AS AddressLine1
FROM MyTable
UNION
SELECT AddressId, 
       CONCAT(coalesce(SubBuildingName,''), ', ',
              coalesce(BuildingNumber,''), ', ',
              coalesce(BuildingName,'')
       ) AS AddressLine1
FROM MyTable
UNION
SELECT AddressId, 
       CONCAT(coalesce(BuildingNumber,''), ', ',
              coalesce(BuildingName,''), ', ',
              coalesce(SubBuildingName,'')
       ) AS AddressLine1
FROM MyTable
UNION
SELECT AddressId, 
       CONCAT(coalesce(BuildingNumber,''), ', ',
              coalesce(SubBuildingName,''), ', ',
              coalesce(BuildingName,'')
       ) AS AddressLine1
FROM MyTable
UNION
SELECT AddressId, 
       CONCAT(coalesce(BuildingName,''), ', ',
              coalesce(SubBuildingName,''), ', ',
              coalesce(BuildingNumber,'')
       ) AS AddressLine1
FROM MyTable
UNION
SELECT AddressId, 
       CONCAT(coalesce(BuildingName,''), ', ',
              coalesce(BuildingNumber,''), ', ',
              coalesce(SubBuildingName,'')
       ) AS AddressLine1
FROM MyTable