我有如下表格
Discese
ID | DisceseNAme
1 | Heart
2 | Lungs
3 | ENT
注册
PatienID | NAME | Discease
1 | abc | 1
2 | asa | 2|3
3 | asd | 1|2|3
我有一个分割|
分隔数据的功能。现在我想要结果为:
PatientID | Name | DisceseNAme
1 | abc | heart
2 |asa | Lungs,ENT
3 |asd | heart,Lungs,ENT
我的分割功能是
ALTER FUNCTION [dbo].[fnSplit](
@sInputList VARCHAR(8000) -- List of delimited items
, @sDelimiter VARCHAR(8000) = '|' -- delimiter that separates items
) RETURNS @List TABLE (item VARCHAR(8000))
BEGIN
DECLARE @sItem VARCHAR(8000)
WHILE CHARINDEX(@sDelimiter,@sInputList,0) <> 0
BEGIN
SELECT
@sItem=RTRIM(LTRIM(SUBSTRING(@sInputList,1,CHARINDEX(@sDelimiter,@sInputList,0)-1))),
@sInputList=RTRIM(LTRIM(SUBSTRING(@sInputList,CHARINDEX(@sDelimiter,@sInputList,0)+LEN(@sDelimiter),LEN(@sInputList))))
IF LEN(@sItem) > 0
INSERT INTO @List SELECT @sItem
END
IF LEN(@sInputList) > 0
INSERT INTO @List SELECT @sInputList -- Put the last item in
RETURN
END
我不知道如何才能得到那个结果。
答案 0 :(得分:2)
正如评论中已经提到的,最好规范化表格结构。这意味着您不应将患者的疾病存储在一个VARCHAR
列中,疾病ID与某些特征分开。相反,您应该将患者的所有疾病存储在不同的行中。
如果您继续使用现在的设置,您的查询将变得非常麻烦,性能将非常糟糕。此外,您将无法使用外键来享受数据库一致性。
我编写了这个示例脚本,最终选择了您需要的输出。该示例使用临时表。如果您选择使用这种工作方式(并且您应该),只需将此设置与常规表一起使用(即不以#
开头)。
表格:
#disease
:定义疾病#patients
:定义患者#registration
:定义患者的疾病; #disease
和#patients
的外键用于数据一致性(确保患者和疾病确实存在于数据库中)如果您想知道最终查询中的FOR XML PATH('')
构造如何产生|
- 分隔VARCHAR
,请阅读this answer我之前就此主题发表过的
-- Diseases
CREATE TABLE #disease(
ID INT,
DiseaseName VARCHAR(256),
CONSTRAINT PK_disease PRIMARY KEY(ID)
);
INSERT INTO #disease(ID,DiseaseName)VALUES
(1,'Heart'),(2,'Lungs'),(3,'ENT');
-- Patients
CREATE TABLE #patients(
PatientID INT,
Name VARCHAR(256),
CONSTRAINT PK_patients PRIMARY KEY(PatientID)
);
INSERT INTO #patients(PatientID,Name)VALUES
(1,'abc'),(2,'asa'),(3,'asd'),(4,'zldkzld');
-- Registration for patient's diseases
CREATE TABLE #registration(
PatientID INT,
Disease INT,
CONSTRAINT FK_registration_to_patient FOREIGN KEY(PatientID) REFERENCES #patients(PatientID),
CONSTRAINT FK_registration_to_disease FOREIGN KEY(Disease) REFERENCES #disease(ID),
);
INSERT INTO #registration(PatientID,Disease)VALUES
(1,1), -- patient with ID 1 has one disease: Heart
(2,2),(2,3), -- patient with ID 2 has two diseases: Lungs and ENT
(3,1),(3,2),(3,3); -- patient with ID 3 has three diseases: Heart, Lungs and ENT
-- Select diseases for partients in one |-separated column
SELECT
p.PatientID,p.Name,Diseases=STUFF(dn.diseases,1,1,'')
FROM
#patients AS p
CROSS APPLY ( -- construct a |-separated column with all diseases for the client
SELECT
'|'+d.DiseaseName
FROM
#registration AS r
INNER JOIN #disease AS d ON
d.ID=r.Disease
WHERE
r.PatientID=p.PatientID
FOR
XML PATH('')
) AS dn(diseases)
WHERE
EXISTS(SELECT 1 FROM #registration AS r WHERE r.PatientID=p.PatientID)
ORDER BY
p.PatientID;
DROP TABLE #disease;DROP TABLE #registration;DROP TABLE #patients;
结果:
+-----------+------+-----------------+
| PatientID | Name | Diseases |
+-----------+------+-----------------+
| 1 | abc | Heart |
| 2 | asa | Lungs|ENT |
| 3 | asd | Heart|Lungs|ENT |
+-----------+------+-----------------+