使用临时表的动态数据透视表
Dynamic Pivot using Temp tables
我有三个查询,它们都构建了三个独立的 table。程序、DRG 和诊断。我不知道患者可能有多少手术、工作 DRG 或诊断。然而,我只需要某些程序代码、DRG 和诊断代码。我在临时 table 中对每个条目进行了排名。我们现在只使用一个 table,因为其他两个的答案是一样的。让我们只处理诊断 Table.
在诊断中 Table 我有一个排名字段,它只会在 Dx_Rank 字段中输入 Dx_1、Dx_2、Dx_3所以我可以把它们拉出来,但我不知道会有多少Dx。我需要这些都在一条线上。所以输出会是这样的。
Patient_Account, Visit_Key, Dx_1, Dx_1_描述, Dx_2, Dx_2_描述, Dx_3, Dx_3_描述
来自 table 看起来像这样
> Patient_Account, Visit_Key, Dx_Code, Dx_Priority, Dx_Rank, Dx_Desctiption
> 123456789, #PAS203234, J20, 3, Dx_1, Left Hip is Broken
> 123456789, #PAS203234, A32, 6, Dx_2, Left Knee is broken
> 123456789, #PAS203234, R4786, 8, Dx_3, Left Ankle is broken
> 987654321, #PAS435678, DF346, 2, Dx_1, Right Arm is broken
> 987654321, #PAS435678, DT342.12, 4, Dx_2, Right Wrist is broken
这里我有两个患者,输出应该是这样的。
Patient_Account, Visit_Key, Dx_1, Dx_1_Description, Dx_2, Dx_2_Description, Dx_3, Dx_3_Description
123456789, #PAS203234, J20, Left Hip is broken, A32, Left Knee is broken, R4786, Left Ankle is broken
987654321, #PAS435678, DF346, Right Arm is broken, DT342.12, Right Wrist is broken, , ,
所以我想我会做一个 PIVOT。我设置了一切,但它没有给我我想要的。我在右栏中得到 Dx_1,但是当有 Dx_2 时,它在右栏中,但它在单独的一行中。我希望这一切都在一行中,因为最终输出将进入 Excel 并且我想让它动态化所以如果我得到的最大诊断是 Dx_3 它会停止并且没有 7 个额外的空白列.如果我将其硬编码为每个都有 10 个,然后当我最终得到一个有 11 个的患者时会发生什么,而我错过了一个,因为我有 10 个诊断的限制。
这是我目前的脚本。
IF OBJECT_ID('tempdb..#PROCEDURES_CPT') IS NOT NULL
DROP TABLE #PROCEDURES_CPT
IF OBJECT_ID('tempdb..#PROCEDURES_CPT_PIVOT') IS NOT NULL
DROP TABLE #PROCEDURE_CPT_PIVOT
IF OBJECT_ID('tempdb..#PROCEDURES_DRG') IS NOT NULL
DROP TABLE #PROCEDURES_DRG
IF OBJECT_ID('tempdb..#PROCEDURES_DRG_PIVOT') IS NOT NULL
DROP TABLE #PROCEDURES_DRG_PIVOT
IF OBJECT_ID('tempdb..#PROCEDURES_DX') IS NOT NULL
DROP TABLE #PROCEDURES_DX
IF OBJECT_ID('tempdb..#PROCEDURES_DX_PIVOT') IS NOT NULL
DROP TABLE #PROCEDURES_DX_PIVOT
IF OBJECT_ID('tempdb..#PATIENTS') IS NOT NULL
DROP TABLE #PATIENTS
IF OBJECT_ID('tempdb..#PATIENTS_FINAL') IS NOT NULL
DROP TABLE #PATIENTS_FINAL
/** DEFINE TABLE AND PARAMETERS **/
/** CREATE THE TABLE FOR THE PATIENTS **/
CREATE TABLE #PATIENTS
(
Patient_Account VARCHAR(20) NOT NULL,
Visit_Key VARCHAR(20) NOT NULL
)
/** DECLARE THE VARIABLES FOR THE TEMP PIVOT TABLES THAT ARE NEEDED FOR THE THREE SECTIONS **/
DECLARE @SQLPIVOT_CPT AS NVARCHAR(MAX)
DECLARE @SQLPIVOT_DRG AS NVARCHAR(MAX)
DECLARE @SQLPIVOT_DX AS NVARCHAR(MAX)
/** DECLARE THE VARIABLE NAME THAT WILL HOLD THE COLUMN NAMES LIKE CPT_1, CPT2, CPT_3, etc OR DRG_1, DRG_2,etc, OR DX_1, DX_2, DX_3, DX_4, etc **/
DECLARE @PivotColumns_CPT AS NVARCHAR(MAX)
DECLARE @PivotColumns_DRG AS NVARCHAR(MAX)
DECLARE @PivotColumns_DX AS NVARCHAR(MAX)
/** CPT CODES **/
SELECT pv.pt_id,
pv.vst_key,
pv.proc_eff_full_date,
pv.prio_cd,
'CPT_' + CONVERT(VARCHAR(10), ROW_NUMBER() OVER(PARTITION BY pv.pt_id ORDER BY pv.prio_cd)) AS 'CPT_Rank',
pv.proc_cd,
pv.alt_clasf_desc,
hrp.Procedure_Type,
UPPER(pv.resp_pract_rpt_name) AS 'Surgeon'
INTO #PROCEDURES_CPT
FROM smsdss.proc_v AS pv INNER JOIN
dbo.BETHESDA_HIGH_RISK_PROCEDURES AS hrp ON pv.proc_cd = hrp.Clinical_Code AND hrp.Report_Type = 'CPT'
WHERE pv.proc_eff_full_date BETWEEN '10/01/2020' AND '09/30/2021'
/** DRG CODES **/
SELECT vv.pt_id,
vv.vst_key,
vv.end_full_date,
vv.drg_no,
UPPER(drg.DRGDesc) AS 'DRG_Description',
hrp.Procedure_Type,
UPPER(vv.adm_pract_rpt_name) AS 'Admitting Physician'
INTO #PROCEDURES_DRG
FROM smsdss.vst_v AS vv INNER JOIN
dbo.BETHESDA_HIGH_RISK_PROCEDURES AS hrp ON vv.drg_no = hrp.Clinical_Code AND hrp.Report_Type = 'DRG' LEFT OUTER JOIN
smsdss.DRGMstr AS drg ON vv.drg_no = drg.DRGNo AND drg.DRGVers = 'MS-V38'
WHERE vv.end_full_date BETWEEN '10/01/2020' AND '09/30/2021'
/** DX CODES **/
SELECT dx.pt_id,
dx.vst_key,
dx.dx_eff_full_date,
dx.dx_type_desc,
'Dx_' + CONVERT(VARCHAR(10), ROW_NUMBER() OVER(PARTITION BY dx.pt_id, dx.dx_type_desc ORDER BY dx.prio_cd)) AS 'Dx_Rank',
dx.prio_cd,
dx.dx_cd,
dx.clasf_desc,
hrp.Procedure_Type
INTO #PROCEDURES_DX
FROM smsdss.dx_grp_v AS dx INNER JOIN
dbo.BETHESDA_HIGH_RISK_PROCEDURES AS hrp ON dx.dx_cd = hrp.Clinical_Code AND hrp.Report_Type = 'ICD-10'
WHERE dx.dx_eff_full_date BETWEEN '10/01/2020' AND '09/30/2021'
GROUP BY dx.pt_id,
dx.vst_key,
dx.dx_eff_full_date,
dx.dx_type_desc,
dx.prio_cd,
dx.dx_cd,
dx.clasf_desc,
hrp.Procedure_Type
ORDER BY dx.pt_id,
dx.dx_type_desc,
dx.prio_cd
/** PIVOT DX **/
SELECT @PivotColumns_DX = COALESCE(@PivotColumns_DX + ', ' , '') + Dx_Rank
FROM #PROCEDURES_DX
GROUP BY Dx_Rank
ORDER BY Dx_Rank
SELECT @PivotColumns_DX
SET @SQLPIVOT_DX = N'SELECT pt_id, vst_key, ' + @PivotColumns_DX + '
INTO #PROCEDURES_DX_PIVOT
FROM #PROCEDURES_DX
PIVOT (MAX(dx_cd)
FOR Dx_Rank IN (' + @PivotColumns_DX + ')) AS tdx'
SELECT @SQLPIVOT_DX
EXEC sp_executesql @SQLPIVOT_DX
SELECT * FROM #PROCEDURES_DX_PIVOT
直到我在最后一行添加尝试 select 来自 Temp Table #PROCEDURES_DX_PIVOT 以查看我有什么之前,我没有收到任何错误。当我 运行 对象无效的代码时出现错误。就像代码没有被执行一样。我创建了一个简单的测试来查看它是否是一个权限,即使我没有收到错误并且我能够创建一些东西。然后我从那个 SELECT @SQLPIVOT_DX
中获取输出,那时我能够看到我的结果以及我如何看到患者是否有 Dx_1 和 Dx_2 它们在两条不同的线上这不是我想要的。我正在尝试将所有内容放在一条线上。
如有任何帮助,我们将不胜感激。如果我的方法不对请告诉我。
美好的一天,很遗憾,您没有提供所有相关实体来重现您的场景并执行您的完整查询,但最后一个主要问题似乎很清楚
I am not getting any errors until I add in the last line a try a select from the Temp Table #PROCEDURES_DX_PIVOT to see what I have. I get an error when I run the code that the Object is not Valid. It is like the code is not being executed.
问题是您在 sp_executesql 的执行范围内创建了临时 table,但您尝试在此范围之外使用它,但它不存在
这是同一问题的简单完整演示
准备
USE tempdb
GO
DROP TABLE IF EXISTS T
GO
create table T(id int)
GO
工作示例,我们在其中创建临时 table 在我们调用它的相同范围内
DROP TABLE IF EXISTS #PROCEDURES_DX_PIVOT
GO
SELECT * INTO #PROCEDURES_DX_PIVOT FROM T
GO
SELECT * FROM #PROCEDURES_DX_PIVOT
GO -- OK, since the temp table was created in the same scope as we call it
错误!无效的对象名称'#PROCEDURES_DX_PIVOT'
DROP TABLE IF EXISTS #PROCEDURES_DX_PIVOT
GO
DECLARE @SQLPIVOT_DX NVARCHAR(MAX)
SET @SQLPIVOT_DX = N'SELECT * INTO #PROCEDURES_DX_PIVOT FROM T'
SELECT @SQLPIVOT_DX
EXEC sp_executesql @SQLPIVOT_DX
SELECT * FROM #PROCEDURES_DX_PIVOT
GO -- Invalid object name '#PROCEDURES_DX_PIVOT'
可选的解决方案是从动态查询内部调用 table
DROP TABLE IF EXISTS #PROCEDURES_DX_PIVOT
GO
DECLARE @SQLPIVOT_DX NVARCHAR(MAX)
SET @SQLPIVOT_DX = N'SELECT * INTO #PROCEDURES_DX_PIVOT FROM T; SELECT * FROM #PROCEDURES_DX_PIVOT;'
SELECT @SQLPIVOT_DX
EXEC sp_executesql @SQLPIVOT_DX
GO -- Invalid object name '#PROCEDURES_DX_PIVOT'
返回您的代码
这与您的代码中的问题相同:
SET @SQLPIVOT_DX = N'SELECT pt_id, vst_key, ' + @PivotColumns_DX + '
INTO #PROCEDURES_DX_PIVOT
FROM #PROCEDURES_DX
PIVOT (MAX(dx_cd)
FOR Dx_Rank IN (' + @PivotColumns_DX + ')) AS tdx'
SELECT @SQLPIVOT_DX
EXEC sp_executesql @SQLPIVOT_DX -- here you use select into to create the temp table
SELECT * FROM #PROCEDURES_DX_PIVOT -- and here you use it outside of the scope which it was created
要在同一行中获取 Patient_Account 的每个 Dx_Code,您需要 GROUP BY Patient_Account
,并使用一些聚合函数(如 MIN() 或 MAX())来得到 Dx_Code 和 Dx_Desctiption.
进行动态查询的另一种方法:
SELECT STRING_AGG(query_piece, '')
FROM (
(SELECT 'SELECT Patient_Account,' AS query_piece)
UNION ALL
(SELECT
CONCAT('MIN(CASE WHEN Dx_Rank = ''', Dx_Rank, ''' THEN Dx_Code END) AS ', Dx_Rank, ', ',
'MIN(CASE WHEN Dx_Rank = ''', Dx_Rank, ''' THEN Dx_Desctiption END) AS ', Dx_Rank, '_Description, ')
FROM Diagnosis
GROUP BY Dx_Rank)
UNION ALL
(SELECT 'Visit_Key
FROM Diagnosis
GROUP BY Patient_Account, Visit_Key;')) AS dynamic_query;
动态查询的结果是您必须执行以获得所需结果的查询:
SELECT Patient_Account,MIN(CASE WHEN Dx_Rank = 'Dx_1' THEN Dx_Code END) AS Dx_1, MIN(CASE WHEN Dx_Rank = 'Dx_1' THEN Dx_Desctiptio END) AS Dx_1_Description, MIN(CASE WHEN Dx_Rank = 'Dx_2' THEN Dx_Code END) AS Dx_2, MIN(CASE WHEN Dx_Rank = 'Dx_2' THEN Dx_Desctiptio END) AS Dx_2_Description, MIN(CASE WHEN Dx_Rank = 'Dx_3' THEN Dx_Code END) AS Dx_3, MIN(CASE WHEN Dx_Rank = 'Dx_3' THEN Dx_Desctiptio END) AS Dx_3_Description, Visit_Key
FROM Diagnosis
GROUP BY Patient_Account, Visit_Key;
输出问题中的示例数据:
Patient_Account
Dx_1
Dx_1_Description
Dx_2
Dx_2_Description
Dx_3
Dx_3_Description
Visit_Key
123456789
J20
Left Hip is Broken
A32
Left Knee is broken
R4786
Left Ankle is broken
#PAS203234
987654321
DF346
Right Arm is broken
DT342.12
Right Wrist is broken
#PAS435678
Sql-Server 2016中的动态查询(无string_agg()函数):
SELECT STUFF((
SELECT ' ' + query_piece
FROM ((SELECT 'SELECT Patient_Account,' AS query_piece)
UNION ALL
(SELECT TOP 100
CONCAT('MIN(CASE WHEN Dx_Rank = ''', Dx_Rank, ''' THEN Dx_Code END) AS ', Dx_Rank, ', ',
'MIN(CASE WHEN Dx_Rank = ''', Dx_Rank, ''' THEN Dx_Desctiption END) AS ', Dx_Rank, '_Description, ')
FROM Diagnosis
GROUP BY Dx_Rank
ORDER BY Dx_Rank ASC)
UNION ALL
(SELECT 'Visit_Key FROM Diagnosis GROUP BY Patient_Account, Visit_Key')) as x
FOR XML PATH('')
), 1, 1, '');
我有三个查询,它们都构建了三个独立的 table。程序、DRG 和诊断。我不知道患者可能有多少手术、工作 DRG 或诊断。然而,我只需要某些程序代码、DRG 和诊断代码。我在临时 table 中对每个条目进行了排名。我们现在只使用一个 table,因为其他两个的答案是一样的。让我们只处理诊断 Table.
在诊断中 Table 我有一个排名字段,它只会在 Dx_Rank 字段中输入 Dx_1、Dx_2、Dx_3所以我可以把它们拉出来,但我不知道会有多少Dx。我需要这些都在一条线上。所以输出会是这样的。
Patient_Account, Visit_Key, Dx_1, Dx_1_描述, Dx_2, Dx_2_描述, Dx_3, Dx_3_描述
来自 table 看起来像这样
> Patient_Account, Visit_Key, Dx_Code, Dx_Priority, Dx_Rank, Dx_Desctiption
> 123456789, #PAS203234, J20, 3, Dx_1, Left Hip is Broken
> 123456789, #PAS203234, A32, 6, Dx_2, Left Knee is broken
> 123456789, #PAS203234, R4786, 8, Dx_3, Left Ankle is broken
> 987654321, #PAS435678, DF346, 2, Dx_1, Right Arm is broken
> 987654321, #PAS435678, DT342.12, 4, Dx_2, Right Wrist is broken
这里我有两个患者,输出应该是这样的。
Patient_Account, Visit_Key, Dx_1, Dx_1_Description, Dx_2, Dx_2_Description, Dx_3, Dx_3_Description 123456789, #PAS203234, J20, Left Hip is broken, A32, Left Knee is broken, R4786, Left Ankle is broken 987654321, #PAS435678, DF346, Right Arm is broken, DT342.12, Right Wrist is broken, , ,
所以我想我会做一个 PIVOT。我设置了一切,但它没有给我我想要的。我在右栏中得到 Dx_1,但是当有 Dx_2 时,它在右栏中,但它在单独的一行中。我希望这一切都在一行中,因为最终输出将进入 Excel 并且我想让它动态化所以如果我得到的最大诊断是 Dx_3 它会停止并且没有 7 个额外的空白列.如果我将其硬编码为每个都有 10 个,然后当我最终得到一个有 11 个的患者时会发生什么,而我错过了一个,因为我有 10 个诊断的限制。
这是我目前的脚本。
IF OBJECT_ID('tempdb..#PROCEDURES_CPT') IS NOT NULL
DROP TABLE #PROCEDURES_CPT
IF OBJECT_ID('tempdb..#PROCEDURES_CPT_PIVOT') IS NOT NULL
DROP TABLE #PROCEDURE_CPT_PIVOT
IF OBJECT_ID('tempdb..#PROCEDURES_DRG') IS NOT NULL
DROP TABLE #PROCEDURES_DRG
IF OBJECT_ID('tempdb..#PROCEDURES_DRG_PIVOT') IS NOT NULL
DROP TABLE #PROCEDURES_DRG_PIVOT
IF OBJECT_ID('tempdb..#PROCEDURES_DX') IS NOT NULL
DROP TABLE #PROCEDURES_DX
IF OBJECT_ID('tempdb..#PROCEDURES_DX_PIVOT') IS NOT NULL
DROP TABLE #PROCEDURES_DX_PIVOT
IF OBJECT_ID('tempdb..#PATIENTS') IS NOT NULL
DROP TABLE #PATIENTS
IF OBJECT_ID('tempdb..#PATIENTS_FINAL') IS NOT NULL
DROP TABLE #PATIENTS_FINAL
/** DEFINE TABLE AND PARAMETERS **/
/** CREATE THE TABLE FOR THE PATIENTS **/
CREATE TABLE #PATIENTS
(
Patient_Account VARCHAR(20) NOT NULL,
Visit_Key VARCHAR(20) NOT NULL
)
/** DECLARE THE VARIABLES FOR THE TEMP PIVOT TABLES THAT ARE NEEDED FOR THE THREE SECTIONS **/
DECLARE @SQLPIVOT_CPT AS NVARCHAR(MAX)
DECLARE @SQLPIVOT_DRG AS NVARCHAR(MAX)
DECLARE @SQLPIVOT_DX AS NVARCHAR(MAX)
/** DECLARE THE VARIABLE NAME THAT WILL HOLD THE COLUMN NAMES LIKE CPT_1, CPT2, CPT_3, etc OR DRG_1, DRG_2,etc, OR DX_1, DX_2, DX_3, DX_4, etc **/
DECLARE @PivotColumns_CPT AS NVARCHAR(MAX)
DECLARE @PivotColumns_DRG AS NVARCHAR(MAX)
DECLARE @PivotColumns_DX AS NVARCHAR(MAX)
/** CPT CODES **/
SELECT pv.pt_id,
pv.vst_key,
pv.proc_eff_full_date,
pv.prio_cd,
'CPT_' + CONVERT(VARCHAR(10), ROW_NUMBER() OVER(PARTITION BY pv.pt_id ORDER BY pv.prio_cd)) AS 'CPT_Rank',
pv.proc_cd,
pv.alt_clasf_desc,
hrp.Procedure_Type,
UPPER(pv.resp_pract_rpt_name) AS 'Surgeon'
INTO #PROCEDURES_CPT
FROM smsdss.proc_v AS pv INNER JOIN
dbo.BETHESDA_HIGH_RISK_PROCEDURES AS hrp ON pv.proc_cd = hrp.Clinical_Code AND hrp.Report_Type = 'CPT'
WHERE pv.proc_eff_full_date BETWEEN '10/01/2020' AND '09/30/2021'
/** DRG CODES **/
SELECT vv.pt_id,
vv.vst_key,
vv.end_full_date,
vv.drg_no,
UPPER(drg.DRGDesc) AS 'DRG_Description',
hrp.Procedure_Type,
UPPER(vv.adm_pract_rpt_name) AS 'Admitting Physician'
INTO #PROCEDURES_DRG
FROM smsdss.vst_v AS vv INNER JOIN
dbo.BETHESDA_HIGH_RISK_PROCEDURES AS hrp ON vv.drg_no = hrp.Clinical_Code AND hrp.Report_Type = 'DRG' LEFT OUTER JOIN
smsdss.DRGMstr AS drg ON vv.drg_no = drg.DRGNo AND drg.DRGVers = 'MS-V38'
WHERE vv.end_full_date BETWEEN '10/01/2020' AND '09/30/2021'
/** DX CODES **/
SELECT dx.pt_id,
dx.vst_key,
dx.dx_eff_full_date,
dx.dx_type_desc,
'Dx_' + CONVERT(VARCHAR(10), ROW_NUMBER() OVER(PARTITION BY dx.pt_id, dx.dx_type_desc ORDER BY dx.prio_cd)) AS 'Dx_Rank',
dx.prio_cd,
dx.dx_cd,
dx.clasf_desc,
hrp.Procedure_Type
INTO #PROCEDURES_DX
FROM smsdss.dx_grp_v AS dx INNER JOIN
dbo.BETHESDA_HIGH_RISK_PROCEDURES AS hrp ON dx.dx_cd = hrp.Clinical_Code AND hrp.Report_Type = 'ICD-10'
WHERE dx.dx_eff_full_date BETWEEN '10/01/2020' AND '09/30/2021'
GROUP BY dx.pt_id,
dx.vst_key,
dx.dx_eff_full_date,
dx.dx_type_desc,
dx.prio_cd,
dx.dx_cd,
dx.clasf_desc,
hrp.Procedure_Type
ORDER BY dx.pt_id,
dx.dx_type_desc,
dx.prio_cd
/** PIVOT DX **/
SELECT @PivotColumns_DX = COALESCE(@PivotColumns_DX + ', ' , '') + Dx_Rank
FROM #PROCEDURES_DX
GROUP BY Dx_Rank
ORDER BY Dx_Rank
SELECT @PivotColumns_DX
SET @SQLPIVOT_DX = N'SELECT pt_id, vst_key, ' + @PivotColumns_DX + '
INTO #PROCEDURES_DX_PIVOT
FROM #PROCEDURES_DX
PIVOT (MAX(dx_cd)
FOR Dx_Rank IN (' + @PivotColumns_DX + ')) AS tdx'
SELECT @SQLPIVOT_DX
EXEC sp_executesql @SQLPIVOT_DX
SELECT * FROM #PROCEDURES_DX_PIVOT
直到我在最后一行添加尝试 select 来自 Temp Table #PROCEDURES_DX_PIVOT 以查看我有什么之前,我没有收到任何错误。当我 运行 对象无效的代码时出现错误。就像代码没有被执行一样。我创建了一个简单的测试来查看它是否是一个权限,即使我没有收到错误并且我能够创建一些东西。然后我从那个 SELECT @SQLPIVOT_DX
中获取输出,那时我能够看到我的结果以及我如何看到患者是否有 Dx_1 和 Dx_2 它们在两条不同的线上这不是我想要的。我正在尝试将所有内容放在一条线上。
如有任何帮助,我们将不胜感激。如果我的方法不对请告诉我。
美好的一天,很遗憾,您没有提供所有相关实体来重现您的场景并执行您的完整查询,但最后一个主要问题似乎很清楚
I am not getting any errors until I add in the last line a try a select from the Temp Table #PROCEDURES_DX_PIVOT to see what I have. I get an error when I run the code that the Object is not Valid. It is like the code is not being executed.
问题是您在 sp_executesql 的执行范围内创建了临时 table,但您尝试在此范围之外使用它,但它不存在
这是同一问题的简单完整演示
准备
USE tempdb
GO
DROP TABLE IF EXISTS T
GO
create table T(id int)
GO
工作示例,我们在其中创建临时 table 在我们调用它的相同范围内
DROP TABLE IF EXISTS #PROCEDURES_DX_PIVOT
GO
SELECT * INTO #PROCEDURES_DX_PIVOT FROM T
GO
SELECT * FROM #PROCEDURES_DX_PIVOT
GO -- OK, since the temp table was created in the same scope as we call it
错误!无效的对象名称'#PROCEDURES_DX_PIVOT'
DROP TABLE IF EXISTS #PROCEDURES_DX_PIVOT
GO
DECLARE @SQLPIVOT_DX NVARCHAR(MAX)
SET @SQLPIVOT_DX = N'SELECT * INTO #PROCEDURES_DX_PIVOT FROM T'
SELECT @SQLPIVOT_DX
EXEC sp_executesql @SQLPIVOT_DX
SELECT * FROM #PROCEDURES_DX_PIVOT
GO -- Invalid object name '#PROCEDURES_DX_PIVOT'
可选的解决方案是从动态查询内部调用 table
DROP TABLE IF EXISTS #PROCEDURES_DX_PIVOT
GO
DECLARE @SQLPIVOT_DX NVARCHAR(MAX)
SET @SQLPIVOT_DX = N'SELECT * INTO #PROCEDURES_DX_PIVOT FROM T; SELECT * FROM #PROCEDURES_DX_PIVOT;'
SELECT @SQLPIVOT_DX
EXEC sp_executesql @SQLPIVOT_DX
GO -- Invalid object name '#PROCEDURES_DX_PIVOT'
返回您的代码
这与您的代码中的问题相同:
SET @SQLPIVOT_DX = N'SELECT pt_id, vst_key, ' + @PivotColumns_DX + '
INTO #PROCEDURES_DX_PIVOT
FROM #PROCEDURES_DX
PIVOT (MAX(dx_cd)
FOR Dx_Rank IN (' + @PivotColumns_DX + ')) AS tdx'
SELECT @SQLPIVOT_DX
EXEC sp_executesql @SQLPIVOT_DX -- here you use select into to create the temp table
SELECT * FROM #PROCEDURES_DX_PIVOT -- and here you use it outside of the scope which it was created
要在同一行中获取 Patient_Account 的每个 Dx_Code,您需要 GROUP BY Patient_Account
,并使用一些聚合函数(如 MIN() 或 MAX())来得到 Dx_Code 和 Dx_Desctiption.
进行动态查询的另一种方法:
SELECT STRING_AGG(query_piece, '')
FROM (
(SELECT 'SELECT Patient_Account,' AS query_piece)
UNION ALL
(SELECT
CONCAT('MIN(CASE WHEN Dx_Rank = ''', Dx_Rank, ''' THEN Dx_Code END) AS ', Dx_Rank, ', ',
'MIN(CASE WHEN Dx_Rank = ''', Dx_Rank, ''' THEN Dx_Desctiption END) AS ', Dx_Rank, '_Description, ')
FROM Diagnosis
GROUP BY Dx_Rank)
UNION ALL
(SELECT 'Visit_Key
FROM Diagnosis
GROUP BY Patient_Account, Visit_Key;')) AS dynamic_query;
动态查询的结果是您必须执行以获得所需结果的查询:
SELECT Patient_Account,MIN(CASE WHEN Dx_Rank = 'Dx_1' THEN Dx_Code END) AS Dx_1, MIN(CASE WHEN Dx_Rank = 'Dx_1' THEN Dx_Desctiptio END) AS Dx_1_Description, MIN(CASE WHEN Dx_Rank = 'Dx_2' THEN Dx_Code END) AS Dx_2, MIN(CASE WHEN Dx_Rank = 'Dx_2' THEN Dx_Desctiptio END) AS Dx_2_Description, MIN(CASE WHEN Dx_Rank = 'Dx_3' THEN Dx_Code END) AS Dx_3, MIN(CASE WHEN Dx_Rank = 'Dx_3' THEN Dx_Desctiptio END) AS Dx_3_Description, Visit_Key
FROM Diagnosis
GROUP BY Patient_Account, Visit_Key;
输出问题中的示例数据:
Patient_Account | Dx_1 | Dx_1_Description | Dx_2 | Dx_2_Description | Dx_3 | Dx_3_Description | Visit_Key |
---|---|---|---|---|---|---|---|
123456789 | J20 | Left Hip is Broken | A32 | Left Knee is broken | R4786 | Left Ankle is broken | #PAS203234 |
987654321 | DF346 | Right Arm is broken | DT342.12 | Right Wrist is broken | #PAS435678 |
Sql-Server 2016中的动态查询(无string_agg()函数):
SELECT STUFF((
SELECT ' ' + query_piece
FROM ((SELECT 'SELECT Patient_Account,' AS query_piece)
UNION ALL
(SELECT TOP 100
CONCAT('MIN(CASE WHEN Dx_Rank = ''', Dx_Rank, ''' THEN Dx_Code END) AS ', Dx_Rank, ', ',
'MIN(CASE WHEN Dx_Rank = ''', Dx_Rank, ''' THEN Dx_Desctiption END) AS ', Dx_Rank, '_Description, ')
FROM Diagnosis
GROUP BY Dx_Rank
ORDER BY Dx_Rank ASC)
UNION ALL
(SELECT 'Visit_Key FROM Diagnosis GROUP BY Patient_Account, Visit_Key')) as x
FOR XML PATH('')
), 1, 1, '');