【问题标题】:Trying to concatenate a comma delimited list from one column with three table joins and getting duplicates尝试从具有三个表连接的列连接逗号分隔列表并获取重复项
【发布时间】:2018-07-15 20:27:30
【问题描述】:

这是我的表格示例:

项目

+----------+---------------+
| txt_item | txt_unique_id |
+----------+---------------+
| Circle   |             1 |
| Square   |             2 |
| Triangle |             3 |
+----------+---------------+

tag_master

+---------+----------+
| txt_tag | opt_type |
+---------+----------+
| red     | color    |
| blue    | color    |
| yellow  | color    |
| large   | size     |
| medium  | size     |
| small   | size     |
+---------+----------+

item_tags

+---------+---------------+
| txt_tag | txt_unique_id |
+---------+---------------+
| red     |             1 |
| blue    |             1 |
| large   |             1 |
| small   |             1 |
| red     |             2 |
| yellow  |             2 |
| small   |             2 |
| medium  |             2 |
| red     |             3 |
| yellow  |             3 |
+---------+---------------+

我想退货:

+----------+----------------------------+
| Circle   | red, blue, large, small    |
| Square   | red, yellow, small, medium |
| Triangle | red, yellow                |
+----------+----------------------------+

这就是我得到的:

+----------+---------------------------------------------+
| Circle   | red, red, red, blue, large, small, small    |
| Square   | red, red, red, yellow, yellow, small, small |
| Triangle | red, red, red, yellow, yellow               |
+----------+---------------------------------------------+

这是我现在的位置:

CREATE TABLE #screening_tags
  (
     txt_unique_id VARCHAR(36),
     tags          VARCHAR(1000)
  )

INSERT INTO #screening_tags
            (txt_unique_id,
             tags)
(SELECT txt_unique_id,
        ( STUFF((SELECT ' , ' + t.txt_tag
                 FROM   item_tags t
                        JOIN tag_master_ tm
                          ON t.txt_tag = tm.txt_tag
                        JOIN items i
                          ON t.txt_unique_id = i.txt_unique_id
                 ORDER  BY opt_type,
                           txt_tage
                 FOR xml path('')), 1, 1, '') )
 FROM   item_tags t)

SELECT *
FROM   #screening_tags

我也尝试过使用 COALESCE,但我遗漏了一些东西。我需要一个 DISTINCT 或其他东西,但我尝试过的一切都不起作用。如果我想按 opt_type 排序,我不能使用 DISTINCT 或 TOP 1。感谢帮助。

【问题讨论】:

    标签: sql ssms


    【解决方案1】:

    尝试删除 tag_master 上的连接 - 查看您的预期结果,您不需要该表中的任何内容。事实上,您似乎不需要任何联接。

        CREATE TABLE #screening_tags
          (
             txt_unique_id VARCHAR(36),
             tags          VARCHAR(1000)
          )
    
        INSERT INTO #screening_tags
                    (txt_unique_id,
                     tags)
        (SELECT txt_unique_id,
                ( STUFF((SELECT ' , ' + t.txt_tag
                         FROM   items i
                         where t.txt_unique_id = i.txt_unique_id
                         ORDER  BY opt_type,
                                   txt_tag
                         FOR xml path('')), 1, 1, '') )
         FROM   item_tags t)
    
        SELECT *
        FROM   #screening_tags
    

    【讨论】:

      【解决方案2】:

      不确定您使用的是什么数据库,但如果是 Postgres,请尝试一下:

      SELECT i.item, string_agg(DISTINCT tm.text_tag,',') AS txt_tag_agg
      FROM items i
      INNER JOIN item_tags it ON i.txt_unique_id = it.txt_unique_id
      INNER JOIN tag_master tm ON it.txt_tag = tm.text_tag
      GROUP BY i.item
      

      string_agg 函数将构建由GROUP BY 列分组的指定行值的聚合字符串。

      【讨论】:

      • 冷静点,伙计。我不知道 SSMS = SQL Server。除此之外,这可以让您了解可能的解决方案的逻辑,即使它不适用于他的特定数据库。
      • 我和你在一起,馄饨!
      【解决方案3】:

      假设您在 SQL-server >= 2017 上,string_agg() 现在可用。

      SQL Fiddle

      MS SQL Server 2017 架构设置

      查询 1

      select i.txt_item , string_agg(it.txt_tag, ',')
      from items i
      inner join item_tags it
        on i.txt_unique_id = it.txt_unique_id
      inner join tag_master tm
        on tm.txt_tag = it.txt_tag
      where opt_type = 'color'
      group by i.txt_item
      

      Results

      | txt_item |            |
      |----------|------------|
      |   Circle |   red,blue |
      |   Square | red,yellow |
      | Triangle | red,yellow |
      

      【讨论】:

      • 不幸的是我在 2016 年。
      【解决方案4】:

      我想通了 - 我必须将 STUFF 子查询链接到 WHERE 子句中的主查询

      CREATE TABLE #screening_tags
        (
           txt_unique_id VARCHAR(36),
           tags          VARCHAR(1000)
        )
      
      INSERT INTO #screening_tags
                  (txt_unique_id,
                   tags)
      (SELECT txt_unique_id,
              ( STUFF((SELECT ', ' + t.txt_tag
                       FROM   item_tags t1
                             WHERE t.txt_unique_id = t2.txt_unique_id
                       FOR xml path('')), 1, 1, '') )
       FROM   item_tags t2)
      
      SELECT *
      FROM   #screening_tags
      
      +----------+----------------------------+
      | Circle   | red, blue, large, small    |
      | Square   | red, yellow, small, medium |
      | Triangle | red, yellow                |
      +----------+----------------------------+
      

      【讨论】:

        【解决方案5】:

        使用子查询至少可以在 sql server、mysql、sqlite 和 postgresql 上工作:

        select i.txt_item, 
        (select string_agg(txt_tag, ',') 
        from item_tags it where i.txt_unique_id=it.txt_unique_id) as txt_tag
        from items i
        

        返回:

        txt_item    txt_tag
        Circle      red,blue,large,small
        Square      red,yellow,small,medium
        Triangle    red,yellow
        

        在 mysql 上使用 group_concat(txt_tag) 而不是 string_agg。 在 postgres 上,使用 array_agg(txt_tag)。

        sqlfiddle.com

        【讨论】:

        • 更新了使用 sql server 的答案。还有埃里克,我不认为工作是用三个感叹号写的,别写了,好吗?
        猜你喜欢
        • 2013-08-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-06
        • 1970-01-01
        • 2014-10-15
        相关资源
        最近更新 更多