使用CAST将行组合成一列时遇到问题(

时间:2011-09-28 18:25:43

标签: sql sql-server

好的,这是你发光的时候了!

不是的,我正在接受一个我似乎无法开始工作的MS-SQL查询。

我要做的是搜索患者姓名;但也要将具有相似名字或姓氏的患者归还给查询患者的姓氏。因此,“约翰史密斯”可以归还任何名为“约翰史密斯”的人或任何名字如“史密斯”的人。如果患者具有多种疾病状态,则将这些疾病状态组合成单个列。我有以下表格(虽然当然有更多列,但这些是最重要的):

Patient Table
PatientID    FirstName    LastName    UserIDFK
10000        John         Smith       1
10001        Miss         Smith       2
10002        Smith        Bomb        3
10003        Bobby        Smith       4
-- etc

DiseaseStateForUser
UserIDFK    DiseaseStateRefId
1           1
1           2
2           2
3           1
3           2
4           1

GlobalLookUp
RefId    Ref_Code
1        HIV
2        HEPC

我正在寻找的结果是:

PatientID    FirstName    LastName    DiseaseStates
10000        John         Smith       HIV|HEPC
10001        Miss         Smith       HEPC
10002        Smith        Bomb        HIV|HEPC
10003        Bobby        Smith       HIV

我从这些问题(以及无数其他问题)中采用了这些例子:

除了这篇博文Emulating MySQL’s GROUP_CONCAT() Function in SQL Server 2005之外,我还提出了以下SQL过程

DECLARE 
    @PatientID          INT=null,           
    @FirstName          Varchar(15)= null,
    @LastName           Varchar(15)= 'Smith',
    @Name           Varchar(15) = 'John Smith',

Select
    Patient.First_Name,
    Patient.Last_Name, 
    patient.PatientID,      
    (select CAST(GlobalLookUp.Ref_Code + '|' as VARCHAR(MAX))
     from 
        TBL_PATIENT patient
        ,TBL_GBLLOOKUP GlobalLookUp
        ,TBL_DiseaseStateForUser DiseaseStateForUser
        -- Try and make a collection of all the PatientIDs
        -- that match the search criteria 
        -- so that only these are used to build
        -- the DiseaseStatesColumn
        ,(Select
            Patient.PatientID
                FROM TBL_PATIENT patient
                    ,TBL_SITEMASTER SiteMaster 
                    ,TBL_USERMASTER UserMaster
                    ,TBL_USERSINSITES UserInSites
                    ,TBL_GBLLOOKUP GlobalLookUp
                    ,TBL_DiseaseStateForUser DiseaseStateForUser
                WHERE   (((patient.[Last_Name] like @LastName + '%') OR (patient.[Last_Name] Like @Name + '%' ))
                            OR ((patient.[First_Name] Like @Name + '%' ))
                            OR  (patient.[First_Name] + ' ' + patient.[Last_Name] Like @Name + '%' ))
                    AND     UserMaster.User_Id = UserInSites.User_Id_FK
                    AND     UserInSites.Site_Id_FK = SiteMaster.Site_Id
                    AND     UserInSites.Is_Active = 'True'
                    AND     patient.[User_Id_FK] = UserMaster.[User_Id] 
                    AND     (DiseaseStateForUser.User_Id_FK = patient.User_Id_FK
                    AND     DiseaseStateForUser.DiseaseState_RefId_FK = GlobalLookUp.Ref_Id)
                    and     DiseaseStateForUser.Is_Active='True'
                    AND     patient.[Is_Active] = 'TRUE'
            group by Patient.PatientID) as PATIENTIDs
    where patient.PatientID = PATIENTIDs.PatientID  
            AND     (DiseaseStateForUser.User_Id_FK = patient.User_Id_FK
            AND     DiseaseStateForUser.DiseaseState_RefId_FK = GlobalLookUp.Ref_Id)
    For XML PATH('')) as MultiDiseaseState

FROM TBL_PATIENT patient, TBL_SITEMASTER SiteMaster ,TBL_USERMASTER UserMaster,TBL_USERSINSITES UserInSites, TBL_GBLLOOKUP GlobalLookUp, TBL_DiseaseStateForUser DiseaseStateForUser
WHERE   (((patient.[Last_Name] like @LastName + '%') OR (patient.[Last_Name] Like @Name + '%' ))
            or ((patient.[First_Name] Like @Name + '%' ))
            OR  (patient.[First_Name] + ' ' + patient.[Last_Name] Like @Name + '%' ))
    AND     patient.PatientID = patient.PatientID
    AND         UserMaster.User_Id = UserInSites.User_Id_FK
    AND     UserInSites.Site_Id_FK = SiteMaster.Site_Id
    AND     UserInSites.Is_Active = 'True'
    AND     patient.[User_Id_FK] = UserMaster.[User_Id] 
    AND     DiseaseStateForUser.User_Id_FK = patient.User_Id_FK
    AND     DiseaseStateForUser.DiseaseState_RefId_FK = GlobalLookUp.Ref_Id
    and     DiseaseStateForUser.Is_Active='True'
    AND     patient.[Is_Active] = 'TRUE'
group by PatientID, patient.First_Name, patient.Last_Name, GlobalLookUp.Ref_Code
order by PatientID

不幸的是,这个查询让我知道以下内容:

PatientID    FirstName    LastName    MultiDiseaseState
10000        John         Smith       HIV|HEPC|HEPC|HIV|HEPC|HIV
10001        Miss         Smith       HIV|HEPC|HEPC|HIV|HEPC|HIV
10002        Smith        Bomb        HIV|HEPC|HEPC|HIV|HEPC|HIV
10003        Bobby        Smith       HIV|HEPC|HEPC|HIV|HEPC|HIV

换句话说,select CAST(GlobalLookUp.Ref_Code + '|' as VARCHAR(MAX))调用正在构建MultiDiseaseState列,其中包含所选患者所有的所有疾病状态。

我知道最内部的SELECT语句存在根本性的错误,但是我很难弄清楚它是什么以及如何编写查询以便它只构建 给定患者的疾病状态。

有点长篇文章,但考虑到我提供的代码片段,人们可以提出任何建议吗?

1 个答案:

答案 0 :(得分:2)

你应该能够使用Stuff功能(我认为它只在SQL 2005及更高版本上)来完成这项工作,我拿了你的示例数据并写了一个演示

    SET NOCOUNT ON

CREATE TABLE #Patient
(
PatientID INT,
FirstName varchar(25),
LastName varchar(25),
UserIDFK INT
)
INSERT INTO #PATIENT SELECT 10000,'John','Smith',1 
INSERT INTO #PATIENT SELECT 10001,'Miss','Smith',2 
INSERT INTO #PATIENT SELECT 10002,'Smith','Bomb',3 
INSERT INTO #PATIENT SELECT 10003,'Bobby','Smith',4 

CREATE TABLE #DiseaseStateForUser 
(
UserIDFK int,
DiseaseStateRefId int
)

INSERT INTO #DiseaseStateForUser SELECT 1,1 
INSERT INTO #DiseaseStateForUser SELECT 1,2 
INSERT INTO #DiseaseStateForUser SELECT 2,2 
INSERT INTO #DiseaseStateForUser SELECT 3,1 
INSERT INTO #DiseaseStateForUser SELECT 3,2 
INSERT INTO #DiseaseStateForUser SELECT 4,1 

CREATE TABLE #GlobalLookUp
(
RefId int,
Ref_Code varchar(10)
)
INSERT INTO #GlobalLookUp SELECT 1,'HIV'
INSERT INTO #GlobalLookUp SELECT 2,'HEPC'


SELECT 
    PatientID,
    UserIDFK,
    FirstName,
    LastName,
    STUFF(
    (SELECT '|' + l.Ref_Code 
    FROM #DiseaseStateForUser u with (Nolock) 
    JOIN dbo.#GlobalLookUp l with (nolock)
        ON u.DiseaseStateRefId = l.RefId
    WHERE u.UserIDFK = p.UserIDFK FOR XML PATH('')
    )
    , 1, 1, '')
FROM #PATIENT p with (Nolock)
GROUP BY PatientID, FirstName, LastName, UserIDFK