1

我想删除一列(设备名称)中的重复项,但保留另一列(app_id)中的相关数据。每个设备可以有几个应用程序(1 -> x,通常在 1-5 之间)所以我想将这些应用程序标识符放入我想调用的新列中 [APP1]、[APP2]、[APP3] 等等. 最好的选择是动态 Pivot,但也欢迎任何静态解决方案。
提前感谢您的帮助。

PS我想出了下面的代码,但只是将用逗号分隔的APP id连接成一列。


    USE tempdb;
    SELECT  DEVICE_NAME,
        NoOfApps,
        STUFF(( SELECT  ', ' + APP_ID
                FROM    dbo.Aperture_full_test apps
                WHERE   apps.DEVICE_NAME = Aperture_full_test.DEVICE_NAME
                FOR XML PATH(''), TYPE
                ).value('.', 'VARCHAR(MAX)'), 1, 2, '') AS Appid

    FROM    (   SELECT  DEVICE_NAME, COUNT(DEVICE_NAME) AS NoOfApps
            FROM    dbo.Aperture_full_test
            GROUP BY DEVICE_NAME     
        ) Aperture_full_test
        ORDER BY NoOfApps DESC 

数据样本:


    USE tempdb;
    GO

    IF OBJECT_ID('dbo.Aperture_full_test') IS NOT NULL
    DROP TABLE dbo.Aperture_full_test;
    GO

    CREATE TABLE dbo.Aperture_full_test
    (
    DEVICE_NAME   varchar(30) NOT NULL,
    APP_ID        varchar(10) NOT NULL
    );

    INSERT INTO dbo.Aperture_full_test(DEVICE_NAME, APP_ID)
    VALUES('LDNSQLF700', 157848);
    INSERT INTO dbo.Aperture_full_test(DEVICE_NAME, APP_ID)
    VALUES('LDNSQLF700', 155439);
    INSERT INTO dbo.Aperture_full_test(DEVICE_NAME, APP_ID)
    VALUES('LDNSQLF700', 635533);
    INSERT INTO dbo.Aperture_full_test(DEVICE_NAME, APP_ID)
    VALUES('NYSQL502', 189164);
    INSERT INTO dbo.Aperture_full_test(DEVICE_NAME, APP_ID)
    VALUES('NYSQL502', 188641);
    INSERT INTO dbo.Aperture_full_test(DEVICE_NAME, APP_ID)
    VALUES('AUSSQL140', 537990);
    INSERT INTO dbo.Aperture_full_test(DEVICE_NAME, APP_ID)
    VALUES('AUSSQL140', 1349605);
    INSERT INTO dbo.Aperture_full_test(DEVICE_NAME, APP_ID)
    VALUES('JAP543X2', 5646789);
    INSERT INTO dbo.Aperture_full_test(DEVICE_NAME, APP_ID)
    VALUES('EU456CLX', 6545789);
    INSERT INTO dbo.Aperture_full_test(DEVICE_NAME, APP_ID)
    VALUES('EUCTX654', 5637965);
    INSERT INTO dbo.Aperture_full_test(DEVICE_NAME, APP_ID)
    VALUES('EUCTX654', 6464367) ;
    INSERT INTO dbo.Aperture_full_test(DEVICE_NAME, APP_ID)
    VALUES('EUCTX654', 1323123) ;
    INSERT INTO dbo.Aperture_full_test(DEVICE_NAME, APP_ID)
    VALUES('EUCTX654', 1004326) ;
    GO
4

2 回答 2

2

由于您使用的是 SQL Server,因此您可以实现PIVOT函数。

如果您有已知数量的值,则可以使用以下命令对查询进行硬编码:

select device_name, App1, App2, App3, App4, App5
from
(
  select device_name, app_id,
    'App'+
      cast(row_number() over(partition by device_name 
                            order by device_name) as varchar(10)) col
  from Aperture_full_test
) d
pivot
(
  max(app_id)
  for col in (App1, App2, App3, App4, App5)
) piv;

请参阅SQL Fiddle with Demo

但是,如果您要为每个设备设置未知数量的 app_id,那么您可以使用动态 SQL:

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT ', ' + QUOTENAME('App'+cast(rn as varchar(10))) 
                    from
                    (
                      select row_number() over(partition by device_name 
                                              order by device_name) rn
                      from Aperture_full_test
                    ) d
                    group by rn
                    order by rn
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT device_name, ' + @cols + ' from 
             (
                select device_name, app_id,
                  ''App''+
                    cast(row_number() over(partition by device_name 
                                          order by device_name) as varchar(10)) col
                from Aperture_full_test
            ) x
            pivot 
            (
                max(app_id)
                for col in (' + @cols + ')
            ) p '

execute(@query)

请参阅SQL Fiddle with Demo。两者都给出结果:

| DEVICE_NAME |    APP1 |    APP2 |    APP3 |    APP4 |
-------------------------------------------------------
|   AUSSQL140 |  537990 | 1349605 |  (null) |  (null) |
|    EU456CLX | 6545789 |  (null) |  (null) |  (null) |
|    EUCTX654 | 5637965 | 6464367 | 1323123 | 1004326 |
|    JAP543X2 | 5646789 |  (null) |  (null) |  (null) |
|  LDNSQLF700 |  157848 |  155439 |  635533 |  (null) |
|    NYSQL502 |  189164 |  188641 |  (null) |  (null) |

编辑,如果要计算每台服务器的设备总数,则可以使用 count() over(). 硬编码版本将是:

select device_name, TotalDevices, App1, App2, App3, App4, App5
from
(
  select device_name, app_id,
    'App'+
      cast(row_number() over(partition by device_name 
                            order by device_name) as varchar(10)) col,
    count(app_id) over(partition by device_name) TotalDevices  -- add this line
  from Aperture_full_test
) d
pivot
(
  max(app_id)
  for col in (App1, App2, App3, App4, App5)
) piv;

请参阅带有演示的 SQL Fiddle

于 2013-04-02T13:58:21.403 回答
0

这是一个数据透视查询,可以在 group by 中完成。您需要的是应用程序的序列号。

select aft.deviceName, COUNT(*) as NumApps,
       MAX(case when seqnum = 1 then App_id end) as App1,
       MAX(case when seqnum = 2 then App_id end) as App2,
       MAX(case when seqnum = 3 then App_id end) as App3,
       MAX(case when seqnum = 4 then App_id end) as App4,
       MAX(case when seqnum = 5 then App_id end) as App5
from (select aft.*,
             ROW_NUMBER() over (partition by device_name order by (select NULL)) as seqnum
      from Aperture_full_test aft
     ) aft
group by aft.deviceName
order by NumApps desc

此版本没有按特定顺序排列的应用程序,因为 xml 代码没有按特定顺序排列它们。

于 2013-04-02T13:44:20.760 回答