简体   繁体   English

SQL服务器中如何使用过滤规则将多行合并为一行

[英]How to merge multiple rows into one row with filtering rules in SQL Server

I have a table like this:我有一张这样的桌子:

+---------------+---------------+----------------+---------------------+
| MedicalCardId | DiagnosisType | DiagnosisOrder |       Symptom       |
+---------------+---------------+----------------+---------------------+
|       1       |      Main     |       1        |     Lung Cancer     |
|       1       |    Secondary  |       1        | High Blood Pressure |
|       1       |    Secondary  |       2        |     Heart Attack    |
|       1       |    Secondary  |       3        |      Gastritis      |
|       2       |      Main     |       1        |      Diabetes       |
|       2       |    Secondary  |       1        |  Kidney Malfunction |
|       3       |      Main     |       1        |         Flu         |
+---------------+---------------+----------------+---------------------+

The DiagnosisOrder for each 'Main' DiagnosisType is 1, and for 'Secondary' DiagnosisType of the same MedicalCardId , it restarts to increase from 1.每个 'Main' DiagnosisTypeDiagnosisOrder为 1,对于相同MedicalCardId的 'Secondary' DiagnosisType ,它从 1 重新开始增加。

I would like to merge multiple rows of the same MedicalCardId into a single row, and each Symptom becomes a new column depending on its DiagnosisType and DiagnosisOrder我想将同一MedicalCardId的多行合并为一行,每个Symptom根据其DiagnosisTypeDiagnosisOrder变成一个新列

The query result is expected to be like:查询结果预计如下:

+---------------+-------------+---------------------+-------------------+-------------------+
| MedicalCardId | MainSymptom |  SecondarySymptom1  | SecondarySymptom2 | SecondarySymptom3 |
+---------------+-------------+---------------------+-------------------+-------------------+
|       1       | Lung Cancer | High Blood Pressure |    Heart Attack   |     Gastritis     |
|       2       |   Diabetes  |  Kidney Malfunction |                   |                   |
|       3       |     Flu     |                     |                   |                   |
+---------------+-------------+---------------------+-------------------+-------------------+

I've tried using PIVOT , but I'm unable to apply it to my practice.我试过使用PIVOT ,但我无法将它应用到我的实践中。

You can try with conditional aggregation -您可以尝试使用条件聚合 -

select MedicalCardId, 
       max(case when DiagnosisType='Main' then Symptom end) as MainSymptom,
       max(case when DiagnosisType='Secondary' and DiagnosisOrder=1 then Symptom end) as SecondarySymptom1,
       max(case when DiagnosisType='Secondary' and DiagnosisOrder=2 then Symptom end) as SecondarySymptom2,
       max(case when DiagnosisType='Secondary' and DiagnosisOrder=3 then Symptom end) as SecondarySymptom3
from tablename
group by MedicalCardId

I believe you need to create a dynamic pivot table.我相信你需要创建一个动态的 pivot 表。 The reason why you can't use a normal pivot table query is because you don't know how many Secondary Symptoms there are and therefore you don't know how many columns to create.不能使用普通的 pivot 表查询的原因是因为不知道有多少次要症状,因此不知道要创建多少列。 Below is a stored procedure that works.下面是一个有效的存储过程。 The first step is creating a VARCHAR (@Columns) variable that will be used to store the dynamic column names these will be [Main], [Secondary1], [Secondary2], [Secondary3] so on and so forth (I used a case statement to create the column names per your expected query result).第一步是创建一个 VARCHAR (@Columns) 变量,该变量将用于存储动态列名称,这些名称将是 [Main]、[Secondary1]、[Secondary2]、[Secondary3] 等等(我使用了一个案例语句来根据您的预期查询结果创建列名)。 The second step is creating another VARCHAR (@SQL) variable that will contain the pivot table SQL query.第二步是创建另一个 VARCHAR (@SQL) 变量,该变量将包含 pivot 表 SQL 查询。 In this step you will use string concatenation to put this variable together.在此步骤中,您将使用字符串连接将此变量放在一起。

Kris Wenzel has a great tutorial on dynamic pivot tables at essentialsql.com here is the link https://www.essentialsql.com/create-dynamic-pivot-table-sql-server/ Kris Wenzel 在 essentialsql.com 上有一个关于动态 pivot 表的精彩教程。这里是链接https://www.essentialsql.com/create-dynamic-pivot-table

Here is the stored procedure.这是存储过程。

USE [TestDB]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

-- =============================================
-- Author:      <Author,,Name>
-- Create date: <Create Date,,>
-- Description: <Description,,>
-- =============================================
CREATE PROCEDURE [dbo].[GenerateData]
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    -- Insert statements for procedure here

--GATHER PIVOT COLUMNS DYNAMICALLY
DECLARE @Columns as VARCHAR(MAX)
SELECT @Columns =
COALESCE(@Columns + ', ','') + QUOTENAME([Diagnosis])
FROM
   (SELECT DISTINCT case when [DiagnosisOrder] = 1 and [DiagnosisType] = 'Main' then 'MainSymptom' else 'SecondarySymptom' + CAST([DiagnosisOrder] AS VARCHAR) end [Diagnosis] FROM [TestDB].[dbo].[test] ) AS B
ORDER BY B.[Diagnosis]

--CREATE SQL QUERY FOR PIVOT TABLE
DECLARE @SQL as VARCHAR(MAX)
SET @SQL = 'SELECT MedicalCardId, ' + @Columns + '
FROM 
(
select [MedicalCardId]
      ,[Diagnosis]
      ,[Sympton]
      from
      (
SELECT [MedicalCardId]
      ,case when [DiagnosisOrder] = 1 and [DiagnosisType] = ''Main'' then ''MainSymptom'' else ''SecondarySymptom'' + CAST([DiagnosisOrder] AS VARCHAR) end [Diagnosis]
      ,[Sympton]
  FROM [TestDB].[dbo].[test]
      ) A
) t 
PIVOT(
    MAX([Sympton])
    FOR [Diagnosis] IN (' + @Columns + ')
) AS pivot_table order by [MedicalCardId]'

--EXECUTE SQL
EXEC(@SQL)

END
GO

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM