Sql选择重复行多列

时间:2015-01-05 18:30:47

标签: sql

我希望有一个查询为每个ComuterName返回一行。该行应包含查询的应用程序及其版本。我目前的查询:

SELECT DISTINCT
  dbo.v_R_System.Name0 [ComputerName],
  dbo.v_GS_ADD_REMOVE_PROGRAMS.DisplayName0 [App],
  dbo.v_GS_ADD_REMOVE_PROGRAMS.Version0
FROM
  dbo.v_R_System 
  INNER JOIN dbo.v_GS_ADD_REMOVE_PROGRAMS
    ON dbo.v_R_System.ResourceID = dbo.v_GS_ADD_REMOVE_PROGRAMS.ResourceID
  INNER JOIN dbo.v_R_User
    ON dbo.v_R_System.User_Name0 = dbo.v_R_User.User_Name0
  INNER JOIN dbo.v_GS_COMPUTER_SYSTEM
    ON dbo.v_R_System.Name0 = dbo.v_GS_COMPUTER_SYSTEM.Name0
  INNER JOIN v_GS_PC_BIOS
    ON dbo.v_R_System.ResourceID = dbo.v_GS_PC_BIOS.ResourceID
WHERE
  dbo.v_GS_ADD_REMOVE_PROGRAMS.DisplayName0 LIKE '%MS Word%'
  OR dbo.v_GS_ADD_REMOVE_PROGRAMS.DisplayName0 LIKE '%Adobe Reader%'
  OR dbo.v_GS_ADD_REMOVE_PROGRAMS.DisplayName0 LIKE '%Flash Player%'

返回:

╔══════════════╦════════════════════╦═════════╗
║ ComputerName ║        App         ║ Version ║
╠══════════════╬════════════════════╬═════════╣
║ PC1          ║ MS Word            ║ 12      ║
║ PC1          ║ Adobe Reader       ║ 10.0.10 ║
║ PC1          ║ Adobe Flash Player ║ 15.1    ║
║ PC2          ║ MS Word            ║ 15      ║
║ PC2          ║ Adobe Reader       ║ 11.0.07 ║
║ PC2          ║ Adobe Flash Player ║ 16      ║
╚══════════════╩════════════════════╩═════════╝

我想以这种方式返回信息:

╔══════════════╦═════════╦═════════╦══════════════╦═════════╦════════════════════╦═════════╗
║ ComputerName ║  App1   ║ App1Ver ║     App2     ║ App2Ver ║        App3        ║ App3Ver ║
╠══════════════╬═════════╬═════════╬══════════════╬═════════╬════════════════════╬═════════╣
║ PC1          ║ MS Word ║      12 ║ Adobe Reader ║ 10.0.10 ║ Adobe Flash Player ║ 15.1    ║
║ PC2          ║ MS Word ║      15 ║ Adobe Reader ║ 11.0.07 ║ Adobe Flash Player ║ 16      ║
╚══════════════╩═════════╩═════════╩══════════════╩═════════╩════════════════════╩═════════╝

此数据库存储在SQL Server 2008 R2上。

提前谢谢。

1 个答案:

答案 0 :(得分:0)

你可以使用case based aggregation,这里有like的另一个问题,因为你使用%通配符不会使用索引,而且在大数据集上会慢一些

最好使用具有组ID列并在应用程序名称和组之间使用映射表,并在查询中使用组ID。

SELECT 
  dbo.v_R_System.Name0 [ComputerName],
  max(case when dbo.v_GS_ADD_REMOVE_PROGRAMS.DisplayName0 LIKE '%MS Word%' then 'MS Word' end ) as App1,
  max(case when dbo.v_GS_ADD_REMOVE_PROGRAMS.DisplayName0 LIKE '%MS Word%' then dbo.v_GS_ADD_REMOVE_PROGRAMS.Version0 end ) as App1Ver
  max(case when dbo.v_GS_ADD_REMOVE_PROGRAMS.DisplayName0 LIKE '%Adobe Reader%' then 'Adobe Reader' end ) as App1,
  max(case when dbo.v_GS_ADD_REMOVE_PROGRAMS.DisplayName0 LIKE '%Adobe Reader%' then dbo.v_GS_ADD_REMOVE_PROGRAMS.Version0 end ) as App2Ver
  max(case when dbo.v_GS_ADD_REMOVE_PROGRAMS.DisplayName0 LIKE '%Flash Player%' then 'Flash Player' end ) as App1,
  max(case when dbo.v_GS_ADD_REMOVE_PROGRAMS.DisplayName0 LIKE '%Flash Player%' then dbo.v_GS_ADD_REMOVE_PROGRAMS.Version0 end ) as App3Ver

FROM
  dbo.v_R_System 
  INNER JOIN dbo.v_GS_ADD_REMOVE_PROGRAMS
    ON dbo.v_R_System.ResourceID = dbo.v_GS_ADD_REMOVE_PROGRAMS.ResourceID
  INNER JOIN dbo.v_R_User
    ON dbo.v_R_System.User_Name0 = dbo.v_R_User.User_Name0
  INNER JOIN dbo.v_GS_COMPUTER_SYSTEM
    ON dbo.v_R_System.Name0 = dbo.v_GS_COMPUTER_SYSTEM.Name0
  INNER JOIN v_GS_PC_BIOS
    ON dbo.v_R_System.ResourceID = dbo.v_GS_PC_BIOS.ResourceID
group by dbo.v_R_System.Name0