Sql 使用行轴删除重复项
我想消除一列(设备名称)中的重复项,但保留另一列(应用程序id)中的相关数据。每个设备可以有两个应用程序(1->x,通常在1-5之间),因此我想将这些应用程序标识符放入一个新的列中,我想调用[APP1]、[APP2]、[APP3]等等。最好的选择是动态轴心,但也欢迎任何静态解决方案Sql 使用行轴删除重复项,sql,sql-server,xml,for-loop,pivot,Sql,Sql Server,Xml,For Loop,Pivot,我想消除一列(设备名称)中的重复项,但保留另一列(应用程序id)中的相关数据。每个设备可以有两个应用程序(1->x,通常在1-5之间),因此我想将这些应用程序标识符放入一个新的列中,我想调用[APP1]、[APP2]、[APP3]等等。最好的选择是动态轴心,但也欢迎任何静态解决方案 提前谢谢你的帮助 PS 我想出了下面的代码,但只将应用程序id由comas分隔成一列 USE tempdb; SELECT DEVICE_NAME, NoOfApps,
提前谢谢你的帮助 PS 我想出了下面的代码,但只将应用程序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
这是一个pivot查询,可以在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代码没有特定顺序的应用程序。因为您使用的是SQL Server,所以可以实现此功能 如果您有已知数量的值,则可以使用以下方法对查询进行硬编码:
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;
看
但如果每个设备的应用程序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)
看。两者都给出了结果:
| 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;
请参阅STUFF((选择DISTINCT',“+APP_)我还有一个问题-是否有机会在动态SQL代码(如上所示)中添加另一列,该列将提供每台服务器的应用程序数?我已尝试了100次修改代码,但似乎失败了,不得不放弃。@Mario是的,您可以在以后使用
count(APP_id)(按设备划分\u名称)
获取每台服务器的设备总数。请参见我的编辑,我添加了一个带有新列的静态查询版本。感谢此代码。它确实有效,而且非常清晰。看起来我终于理解了“over partytion by”过程。