如何从重复行中检索不同的属性到新列?

时间:2017-10-23 10:05:52

标签: sql sql-server

我有一个看起来像这样的表:

att1 att2
| a | 1 |
| a | 2 |
| b | 2 |
| b | 3 |

我需要att1的不同记录,将att1上的重复值分组到一个新列中,如下所示

att1 att2 att3
| a | 1 | 2 |
| b | 2 | 3 |

我试图转动,我试图自我加入,但我似乎无法找到查询来分隔这样的值。有人可以帮帮我吗?感谢

4 个答案:

答案 0 :(得分:0)

简单地使用StuffXML的方法来实现上述结果很简单。

SELECT DISTINCT
       AA.att1,
       split.a.value('/X[1]', 'NVARCHAR(MAX)') [att2],
       split.a.value('/X[2]', 'NVARCHAR(MAX)') [att3]
FROM
(
    SELECT A.att1,
           CAST('<X>'+REPLACE(A.att2, ',', '</X><X>')+'</X>' AS XML) AS String
    FROM
    (
        SELECT DISTINCT
               T.att1,
               att2 = STUFF(
                           (
                               SELECT DISTINCT
                                      ','+att2
                               FROM <table_name>
                               WHERE att1 = T.att1 FOR XML PATH('')
                           ), 1, 1, '')
        FROM <table_name> T
    ) A
) AA
CROSS APPLY String.nodes('/X') AS split(a);

最终结果:

att1 att2 att3
| a | 1 | 2 |
| b | 2 | 3 |

答案 1 :(得分:0)

如果您有已知或最大数量的列,并且您不想动态

示例

Select att1
      ,att2 = max(case when RN=2 then att2 end)
      ,att3 = max(case when RN=3 then att2 end)
 From ( 
        Select *
              ,RN = 1+Row_Number() over (Partition By att1 order by att2)
         From  YourTable
       ) A
 Group By att1

<强>返回

att1    att2    att3
a       1       2
b       2       3

答案 2 :(得分:0)

您可以使用XML Path和内置STUFF函数的组合编写查询。通过这种方式,您可以通过动态列计数获得所需的结果。

请参阅此页面以获取示例:

https://www.sqlshack.com/multiple-options-to-transposing-rows-into-columns/

以及上面页面中的示例查询,它可以满足您的需求:

DECLARE @cols NVARCHAR(MAX), @query NVARCHAR(MAX);
SET @cols = STUFF(
                 (
                     SELECT DISTINCT
                            ','+QUOTENAME(c.[DocName])
                     FROM [dbo].[InsuranceClaims] c FOR XML PATH(''), TYPE
                 ).value('.', 'nvarchar(max)'), 1, 1, '');
SET @query = 'SELECT [PolNumber], '+@cols+'from (SELECT [PolNumber],
           [PolType],
           [submitted] AS [amount],
           [DocName] AS [category]
    FROM [dbo].[InsuranceClaims]
    )x pivot (max(amount) for category in ('+@cols+')) p';
EXECUTE (@query);

答案 3 :(得分:0)

试试此代码

IF OBJECT_ID('tempdb..#t') IS NOT NULL
DROP TABLE #t

CREATE TABLE #t(att1 VARCHAR(10) ,att2 INT)
INSERT INTO #t(att1,att2)

SELECT  'a' AS att1, 1 AS att2 UNION ALL
SELECT  'a' , 2 UNION ALL
SELECT  'b' , 2 UNION ALL
SELECT  'b' , 3 

SELECT * FROM #t

使用lag和cte我们可以得到结果

 ;With cte
AS
(
SELECT        
         Att1, 
         Att2, 
         CASE 
           WHEN Att1 = Att3 THEN MAX(Att2)OVER(Partition by Att1 order by Att1) 
         END att3 
         FROM   (

         SELECT Att1, 
                        Lag(Att1, 1) 
                          OVER ( 
                            ORDER BY Att1)AS att3, 
                        Att2 
                 FROM   #t
                 )dt
    ),
    CTe2
    AS
    (

    SELECT *, 
                ROW_NUMBER() 
                  OVER( 
                    PARTITION BY Att1
                    ORDER BY Att1) AS RNk 
         FROM   (SELECT DISTINCT Att1, 
                                 Att2, 
                                 Max(Att3) 
                                   OVER( 
                                    Partition by Att1 ORDER BY Att1) AS att3 
                 FROM   cte)dt
                 )

  SELECT att1,Att2,att3 FROM CTe2 WHERE RNk=1

结果

Att1    Att2    Att3
---------------------
a       1       2
b       2       3