我想删除一列(device_name)中的重复项,但保留另一列(app_id)中的相关数据。每个设备可以有几个应用程序(1 - > x,通常在1-5之间),所以我想将这些应用程序标识符放入我想调用的新列中[APP1],[APP2],[APP3]等等上。最好的选择是动态Pivot,但任何静态解决方案也将受到欢迎。
提前感谢您的帮助。
PS 我提出了下面的代码,但是只将连接的id id由comas分隔成一列。
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
答案 0 :(得分: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;
但是如果你要为每个设备提供未知数量的app_ids,那么你可以使用动态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;
答案 1 :(得分: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代码没有按特定顺序排列,因此该版本没有特定顺序的应用程序。