As already mentioned in the comments, it is better to normalize your table structure. What this means is that you should not store patient's diseases in one VARCHAR
column with disease ID's separated with some character. Instead you should store all diseases for a patient in separate rows.
If you keep using the setup you have now, your queries will become real cumbersome and performance will be really bad. Also, you will not be able to enjoy database consistency by using foreign keys.
I've written this example script which finally selects for the output you require. The example uses temporary tables. If you choose to use this way of working (and you should), just use this setup with regular tables (ie not starting with #
).
The tables:
#disease
: Defines diseases
#patients
: Defines patients
#registration
: Defines patients' diseases; foreign keys to #disease
and #patients
for data consistency (make sure the patients and diseases actually exist in the database)
If you're wondering how the FOR XML PATH('')
construct in the final query results in a |
-separated VARCHAR
, read this answer I gave a while ago on this subject.
-- 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;
Results:
+-----------+------+-----------------+
| PatientID | Name | Diseases |
+-----------+------+-----------------+
| 1 | abc | Heart |
| 2 | asa | Lungs|ENT |
| 3 | asd | Heart|Lungs|ENT |
+-----------+------+-----------------+