【问题标题】:SQL - Comma Delimited subset results of multiple column in its own columnSQL - 在自己的列中多列的逗号分隔子集结果
【发布时间】:2018-04-28 02:00:39
【问题描述】:

我有一个联合所有表的视图,一个人可能属于一个或多个表。 我如何创建一个查询,该查询将添加一个带有“;”的列以人所属的地方为界,ID 对每个人都是唯一的。 这是示例

--table1
PID  fName  tableMem
1    test   group1
2    test2  group1

--table2
PID  fName  tableMem
1    test   group2
3    test3  group2

--table3
PID  fName  tableMem
1    test   group3
3    test3  group3

这是我想要的输出

--compiled table after union of all the 3 tables
PID  fname  tableMem 
1    test   group1;group2;group3
2    test2  group1
3    test3  group2;group3

这是我过去 2 天在此处阅读时构建的查询。我正在使用 STUFF 和分区,因为我需要使行不同,并且此查询将作为视图运行。

SELECT * 
FROM
    (SELECT 
         *,
         ROW_NUMBER() OVER(PARTITION BY PIP ORDER BY Fname) AS rownum
     FROM 
         (SELECT 
              *,
              STUFF((SELECT ';'+ di.tablemem
                     FROM DPI di  <<-- alias table from union
                     WHERE DPI.PID = di.PID
                     FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '') tablemem
          FROM
              (SELECT * 
               FROM
                   (--table1
                    SELECT 'group1' AS tableMem, * FROM table1
                    UNION ALL
                    --table2
                    SELECT 'group2' AS tableMem, * FROM table2
                    UNION ALL
                    --table3
                    SELECT 'group3' AS tableMem, * FROM table3) AS DPI <<--alias table name
              ) AS innertable
         ) AS distinctTable 
    ) AS outerTable
WHERE
    rownum = 1

我遗漏了什么或查询有什么问题。我猜是因为我使用了联合子选择的派生表名。有什么解决办法吗?

提前谢谢你

【问题讨论】:

    标签: sql-server tsql


    【解决方案1】:

    您需要PID, fNameGROUP BY 数据,使用FOR XML 聚合将是

    WITH DPI AS (
        --table1
        Select 'group1' as tableMem,* from table1
    
        UNION ALL
    
        --table2
        Select 'group2' as tableMem,* from table2
    
        UNION ALL
    
        --table3
        Select 'group3' as tableMem,* from table3
    )
    SELECT PID, fName
        , STUFF((
                SELECT ';'+ di.tablemem
                FROM DPI di  
                WHERE di.PID = di1.PID
                FOR XML PATH(''),TYPE).value('.','NVARCHAR(MAX)'),1,1,'') tablemem
    FROM DPI di1
    GROUP BY PID, fName;
    

    【讨论】:

      【解决方案2】:

      这是使用CTE 的可能解决方案:

      ;with cte as (
          select * from @tbl1
          union all
          select * from @tbl2
          union all
          select * from @tbl3
      )
      select distinct
          pid
          ,fname
          ,stuff(
              (select '; ' + tableMem
              from cte
              where pid = a.pid
                  and fname = a.fname
              FOR XML PATH(''),TYPE)
        .value('text()[1]','nvarchar(max)'),1,2,N'') as tableMem 
      from cte a
      

      【讨论】:

        【解决方案3】:

        鉴于您的表格数量有限,我认为这更简单:

        select p.pid, p.fname,
               trim(';' from
                     (case when t1.pid is not null then 'group1;' else '' end) +
                     (case when t2.pid is not null then 'group2;' else '' end) +
                     (case when t3.pid is not null then 'group3;' else '' end)
                   ) as groups
        from (select pid, fname from table1 union  -- on purpose to remove duplicates
              select pid, fname from table2 union
              select pid, fname from table3
             ) p left join
             table1 t1
             on t1.pid = p.pid left join
             table2 t2
             on t2.pid = p.pid left join
             table3 t3
             on t3.pid = p.pid;
        

        最新版本的 SQL Server 支持string_agg(),这将更加简单。

        【讨论】:

          【解决方案4】:

          试试这个:

          DECLARE @table1 TABLE
          (
              [PID] TINYINT
             ,[fname] VARCHAR(12)
             ,[tableMem] VARCHAR(12)
          );
          
          DECLARE @table2 TABLE
          (
              [PID] TINYINT
             ,[fname] VARCHAR(12)
             ,[tableMem] VARCHAR(12)
          );
          
          DECLARE @table3 TABLE
          (
              [PID] TINYINT
             ,[fname] VARCHAR(12)
             ,[tableMem] VARCHAR(12)
          );
          
          INSERT INTO @table1 ([PID], [fname], [tableMem])
          VALUES (1, 'test', 'group1')
                ,(2, 'test2', 'group1');
          
          INSERT INTO @table2 ([PID], [fname], [tableMem])
          VALUES (1, 'test', 'group2')
                ,(3, 'test3  ', 'group2');
          
          INSERT INTO @table3 ([PID], [fname], [tableMem])
          VALUES (1, 'test', 'group3')
                ,(3, 'test3  ', 'group3');
          
          
          WITH DataSource AS
          (
              SELECT *
              FROM @table1
              UNION ALL
              SELECT *
              FROM @table2
              UNION ALL
              SELECT *
              FROM @table3
          )
          SELECT DISTINCT DS.[PID]
                         ,DS.fname
                         ,CSVvalue.[tableMem]
          FROM DataSource DS
          CROSS APPLY
          (   
              SELECT STUFF
              (
                  (
                      SELECT ',' + DS1.[tableMem]
                      FROM DataSource DS1
                      WHERE DS.[PID] = DS1.[PID]
                          AND DS.[fname] = DS1.[fname]
                      ORDER BY DS1.[tableMem]
                      FOR XML PATH(''), TYPE
                  ).value('.', 'VARCHAR(MAX)')
                  ,1
                  ,1
                  ,''
              )
          ) CSVvalue ([tableMem]);
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-11-17
            • 1970-01-01
            相关资源
            最近更新 更多