I am using SQL Server 2008 R2 version 10.50.1600.1.
I'm trying to pivot a table with strings but the pivot column shares the same name. This is what my data looks like.
+------------+-----------+------------+ | patient_ID | code_type | code_value | +------------+-----------+------------+ | 1 | ICD9 | V70 | | 1 | ICD9 | 401.9 | | 1 | ICD9 | 616 | | 1 | ICD9 | 338.21 | | 2 | ICD9 | V10 | | 2 | ICD9 | 250 | +------------+-----------+------------+
What I'm trying to get to is this ...
+------------+--------+--------+--------+--------+--------+--------+ | patient_id | ICD9_1 | ICD9_2 | ICD9_3 | ICD9_4 | ICD9_5 | ICD9_x | +------------+--------+--------+--------+--------+--------+--------+ | 1 | V70 | 401.9 | 616 | 338.21 | null | null | | 2 | V10 | 250 | null | null | null | null | +------------+--------+--------+--------+--------+--------+--------+
ICD9_x can stretch to infinity because I don't know how many ICD9 codes there will be for a given patient.
Is there a way to do this in SQL?
Thanks!
Update:
Thanks for all the help! I have received two errors. It looks like pivoting requires the values to be an int because of the sum right? Is there a way to use the pivot table for string values? The ICD9 codes are all strings.
Secondly, I hit an unexpected error. It says that "the number of elements in the select list exceeds the maximum allowed number of 4096 elements." Is there a solution for a large data set?
Thanks again!
答案 0 :(得分:0)
You can Try something like this. I hope that Works for you.
DECLARE @cols as varchar(max)
DECLARE @query as varchar(max)
select @cols = (SELECT STUFF((SELECT ',' + QUOTENAME(t.code_type+CAST(row_number() over (partition by patient_id order by patient_id, code_type) as varchar(10)))
FROM YOURTABLE as t
FOR XML PATH('')),1,1,''))
select @query = 'select patient_id, ' + @cols + ' from
(select
code_type+CAST(row_number() over (partition by patient_id order by patient_id, code_type) as varchar(10)) as code_type, SUM(code_value) as code_value from YOURTABLE
group by
code_type+CAST(row_number() over (partition by patient_id order by patient_id, code_type) as varchar(10))) d
Pivot (SUM(code_value) for code_type in (' + @cols + ')) p'
EXECUTE(@query)
答案 1 :(得分:0)
您是否有主键或任何列用于订购以确保代码的顺序正确?
如果你有一个,那么你可以将code_type值连接到以下输出:
row_number () OVER (PARTITION BY patient_ID, code_type ORDER BY patient_id, /* codes order column here */)
...然后你就可以将PIVOT(technet info)与连接值一起使用。
以下是一些代码来说明我的意思:
-- Preparing some demo data as per your sample:
DECLARE @YourTable TABLE (
ID INT IDENTITY (1,1) PRIMARY KEY,
patient_id INT,
code_type VARCHAR(20),
code_value VARCHAR(20)
)
INSERT INTO @YourTable
(patient_id, code_type, code_value)
VALUES
(1, 'ICD9', 'V70'),
(1, 'ICD9', '401.9'),
(1, 'ICD9', '616'),
(1, 'ICD9', '338.21'),
(2, 'ICD9', 'V10'),
(2, 'ICD9', '250')
-- That should look like your starting point:
SELECT * FROM @YourTable
-- Now we suffix the code_type:
SELECT
patient_id,
code_type + '_' + cast(
row_number () OVER (PARTITION BY patient_id, code_type ORDER BY patient_id, ID)
AS VARCHAR(20)
) AS code_type,
code_value
FROM
@YourTable
-- ... and finally we pivot:
SELECT
patient_id,
ICD9_1,
ICD9_2,
ICD9_3,
ICD9_4
FROM (
SELECT
patient_id,
code_type + '_' + cast(
row_number () OVER (PARTITION BY patient_id, code_type ORDER BY patient_id, ID)
AS VARCHAR(20)
) AS code_type,
code_value
FROM
@YourTable
) data
PIVOT (
max(code_value)
-- you need to list all here:
FOR code_type IN (ICD9_1, ICD9_2, ICD9_3, ICD9_4)
) piv