SQL - 按唯一列集

时间:2016-01-25 18:52:07

标签: sql sql-server postgresql

建立问题“SQL - Turn relationship IDs into a delimited list”,我想通过独特的网站集进一步对结果进行分组。例如,在该问题中使用相同的数据:

orig data

网站15& 16一起共享a,b,c的一个排列。站点18,19,20共享另一种排列。站点17使用BOTH排列。

我想查找一个查询结果与链接问题相似,但在site_ids中没有任何重叠:

enter image description here

我不确定只有SQL才有可能,我可能只需要构建一些东西来破解代码中的数据,但我正在喋喋不休......

我正在使用SQL Server,但知道如何使用postgres也很好。

更新:
有人建议Simulating group_concat MySQL function in Microsoft SQL Server 2005?可能是重复的。根据我对group_concat的(有限)理解,它似乎可能会复制question referenced above,但不会复制此问题。这个问题在site_ids中不需要重叠。

2 个答案:

答案 0 :(得分:3)

我不知道这是否是最有效的方法,但确实很有趣。 :)

;WITH CTE_unique_groups AS (SELECT DISTINCT a, b, c FROM dbo.My_Table),
CTE_numbered_groups AS (SELECT a, b, c, ROW_NUMBER() OVER(ORDER BY a, b, c) AS row_num FROM CTE_unique_groups),
CTE_exponented_groups AS (SELECT a, b, c, POWER(2, row_num) AS group_value FROM CTE_numbered_groups),
CTE_unique_sets AS (
    SELECT
        MT.site_id,
        SUM(grps.group_value) AS total_group_value
    FROM
        CTE_exponented_groups AS grps
    INNER JOIN dbo.My_Table MT ON MT.a = grps.a AND MT.b = grps.b AND MT.c = grps.c
    GROUP BY
        MT.site_id
),
CTE_grouped_sites AS
(SELECT total_group_value, STUFF((SELECT ', ' + CAST(site_id AS VARCHAR(10)) FROM CTE_unique_sets t2 WHERE t2.total_group_value = t1.total_group_value FOR XML PATH('')), 1, 2, '') AS site_ids
FROM CTE_unique_sets t1)
SELECT DISTINCT
    x.a, x.b, x.c, gs.site_ids
FROM
    CTE_grouped_sites gs
INNER JOIN CTE_exponented_groups x ON
    gs.total_group_value & x.group_value = x.group_value

它的要点是首先必须识别每组唯一的组。完成后,您可以使用按位&运算符将网站ID分解回其所属的组。

答案 1 :(得分:0)

如果你对一个数组(可以用你的方式将其自身表示为逗号分隔的字符串)表示正常,那么这是PostgreSQL中的一种可能的方法。

with perms as (
  select
    f.a, f.b, f.c, f.site_id,
    count(1) over (partition by f.site_id) as cnt
  from
    your_table f
)
select
  p1.a, p1.b, p1.c,
  array (select p2.site_id
         from perms p2
         where
           p1.a = p2.a and
           p1.b = p2.b and
           p1.c = p2.c and
           p1.cnt = p2.cnt)
from perms p1
group by
  p1.a, p1.b, p1.c, p1.cnt

结果如下:

bar    baz    blah    {20,18,19}
foo    bar    baz     {17}
foo    bar    baz     {16,15}
bar    baz    blah    {17}