在 SQL 中是否有 XML PATH 的替代方案
Is there an alternative for XML PATH in SQL
我正在开发诊所管理应用程序。
在那个应用程序中有一个部分,医生可以选择在他们提供的每项服务中使用什么。
例如,医生给病人做检查时,一副手套和一根木棍被用掉了。
我使用了一个简单的技巧,我在服务 table 中创建了一个字符串,该字符串的 ID 用逗号分隔(类似于 1,3,7,
)并且它工作正常,除了一个案例。
这种情况是当我想将用完的项目名称显示为多个服务的一列时。
我得到服务项目一加服务二等等作为所有服务的一个字符串。
有什么办法可以解决吗?
我知道这听起来很复杂,但如果它有效,你会读到很多其他人。
我使用的加入方式是:
on CHARINDEX(CAST(TblSupply.IDSupply as varchar(10)), TblService.UsedSupplyIDs) > 0
只是我将已用物品 ID TblSupply.IDSupply
转换为字符串,然后检查它是否存在于服务中 table。
当我显示为单独的列时,它工作正常,但我为同一服务获得多行,如下所示:
Select
TblService.ServiceName,
TblSupply.SupplyName
from
TblService
left join TblSupply on CHARINDEX(CAST(TblSupply.IDSupply as varchar(10)), TblService.UsedSupplyIDs) > 0
例如
_____________________________________________
|TblService.ServiceName|TblSupply.SupplyName |
|Patient examination |Glove |
|Patient examination |wood stick |
|Patient examination |thermometer |
|Sonar examination |Glove |
|Sonar examination |lubricating Gel |
|Consultation |Glove |
|______________________|_____________________|
我想得到
________________________________________________________
|TblService.ServiceName|xxxxx |
|Patient examination |Glove ,wood stick , thermometer |
|Sonar examination |Glove,lubricating Gel |
|Consultation |Glove |
我做的代码
Select
TblService.ServiceName,TempTable.SupplyList
from
TblService
left join (Select TblService.IDService As IDService,
STUFF((Select ', ' + TblSupply.SupplyName
FROM
TblService
left join TblSupply on CHARINDEX(CAST(TblSupply.IDSupply as varchar(10)), TblService.UsedSupplyIDs) > 0
FOR XML PATH('')), 1, 1, '') as SupplyList
FROM
TblService
GROUP BY
TblService.IDService
) as TempTable on TempTable.IDService=TblService.IDService
我试过了
Select
TblPatientService.IDPatientService,
TblService.ServiceName,
TempTable.SupplyList
from
TblPatientService
left Join TblService On TblService.IDService = TblPatientService.IDService
left join (Select TblPatientService.IDPatientService As IDPatientService
STUFF((Select ', ' + TblSupply.SupplyName
FROM
TblPatientService
left join TblService on TblService.IDService = TblPatientService.IDService
left join TblSupply on CHARINDEX(CAST(TblSupply.IDSupply as varchar(10)), TblService.UsedSupplyIDs) > 0
WHERE
TblPatientService.IDService = TblService.IDService
FOR XML PATH('')), 1, 1, '') as SupplyList
FROM
TblPatientService
left Join TblService On TblService.IDService = TblPatientService.IDService
GROUP BY
TblPatientService.IDPatientService
) as TempTable on TempTable.IDPatientService = TblPatientService.IDPatientService
我真正得到的
|TblService.ServiceName|xxxxx
|Patient examination |Glove ,wood stick , thermometer,Glove,lubricating Gel,Glove,lubricating Gel |
|Sonar examination |Glove ,wood stick , thermometer,Glove,lubricating Gel,Glove,lubricating Gel |
|Consultation |Glove ,wood stick , thermometer,Glove,lubricating Gel,Glove,lubricating Gel |
换句话说,我得到了所有服务的所有使用过的项目,就好像它们用于所有显示的一项服务一样。
从 SQL Server 2017 开始,您可以使用 STRING_AGG。像 :
SELECT TblPatientService.IDPatientService AS IDPatientService,
STRING_AGG(TblSupply.SupplyName, ', ') AS SupplyList
FROM TblPatientService
LEFT OUTER JOIN TblService ON TblService.IDService = TblPatientService.IDService
LEFT OUTER JOIN TblSupply ON CHARINDEX(CAST(TblSupply.IDSupply AS VARCHAR(10)), TblService.UsedSupplyIDs) > 0
GROUP BY TblPatientService.IDPatientService;
替换 XML 东西!
评论太长了。
我强烈建议修复您的数据模型。在数据库列中存储分隔列表是一种典型的设计反模式,它会以不同的方式适得其反(复杂性、效率、维护、数据完整性)。您可以查看 this famous SO question 了解更多详情。
举个例子:对于一些长度超过一位数的供应 ID(通常 1 会匹配 10),您当前的加入条件不会达到您的预期。
您应该标准化您的模型并有一个单独的 table 来存储服务和用品之间的 N-M 关系,每行一个元组。
我正在开发诊所管理应用程序。
在那个应用程序中有一个部分,医生可以选择在他们提供的每项服务中使用什么。
例如,医生给病人做检查时,一副手套和一根木棍被用掉了。
我使用了一个简单的技巧,我在服务 table 中创建了一个字符串,该字符串的 ID 用逗号分隔(类似于 1,3,7,
)并且它工作正常,除了一个案例。
这种情况是当我想将用完的项目名称显示为多个服务的一列时。
我得到服务项目一加服务二等等作为所有服务的一个字符串。
有什么办法可以解决吗?
我知道这听起来很复杂,但如果它有效,你会读到很多其他人。
我使用的加入方式是:
on CHARINDEX(CAST(TblSupply.IDSupply as varchar(10)), TblService.UsedSupplyIDs) > 0
只是我将已用物品 ID TblSupply.IDSupply
转换为字符串,然后检查它是否存在于服务中 table。
当我显示为单独的列时,它工作正常,但我为同一服务获得多行,如下所示:
Select
TblService.ServiceName,
TblSupply.SupplyName
from
TblService
left join TblSupply on CHARINDEX(CAST(TblSupply.IDSupply as varchar(10)), TblService.UsedSupplyIDs) > 0
例如
_____________________________________________
|TblService.ServiceName|TblSupply.SupplyName |
|Patient examination |Glove |
|Patient examination |wood stick |
|Patient examination |thermometer |
|Sonar examination |Glove |
|Sonar examination |lubricating Gel |
|Consultation |Glove |
|______________________|_____________________|
我想得到
________________________________________________________
|TblService.ServiceName|xxxxx |
|Patient examination |Glove ,wood stick , thermometer |
|Sonar examination |Glove,lubricating Gel |
|Consultation |Glove |
我做的代码
Select
TblService.ServiceName,TempTable.SupplyList
from
TblService
left join (Select TblService.IDService As IDService,
STUFF((Select ', ' + TblSupply.SupplyName
FROM
TblService
left join TblSupply on CHARINDEX(CAST(TblSupply.IDSupply as varchar(10)), TblService.UsedSupplyIDs) > 0
FOR XML PATH('')), 1, 1, '') as SupplyList
FROM
TblService
GROUP BY
TblService.IDService
) as TempTable on TempTable.IDService=TblService.IDService
我试过了
Select
TblPatientService.IDPatientService,
TblService.ServiceName,
TempTable.SupplyList
from
TblPatientService
left Join TblService On TblService.IDService = TblPatientService.IDService
left join (Select TblPatientService.IDPatientService As IDPatientService
STUFF((Select ', ' + TblSupply.SupplyName
FROM
TblPatientService
left join TblService on TblService.IDService = TblPatientService.IDService
left join TblSupply on CHARINDEX(CAST(TblSupply.IDSupply as varchar(10)), TblService.UsedSupplyIDs) > 0
WHERE
TblPatientService.IDService = TblService.IDService
FOR XML PATH('')), 1, 1, '') as SupplyList
FROM
TblPatientService
left Join TblService On TblService.IDService = TblPatientService.IDService
GROUP BY
TblPatientService.IDPatientService
) as TempTable on TempTable.IDPatientService = TblPatientService.IDPatientService
我真正得到的
|TblService.ServiceName|xxxxx
|Patient examination |Glove ,wood stick , thermometer,Glove,lubricating Gel,Glove,lubricating Gel |
|Sonar examination |Glove ,wood stick , thermometer,Glove,lubricating Gel,Glove,lubricating Gel |
|Consultation |Glove ,wood stick , thermometer,Glove,lubricating Gel,Glove,lubricating Gel |
换句话说,我得到了所有服务的所有使用过的项目,就好像它们用于所有显示的一项服务一样。
从 SQL Server 2017 开始,您可以使用 STRING_AGG。像 :
SELECT TblPatientService.IDPatientService AS IDPatientService,
STRING_AGG(TblSupply.SupplyName, ', ') AS SupplyList
FROM TblPatientService
LEFT OUTER JOIN TblService ON TblService.IDService = TblPatientService.IDService
LEFT OUTER JOIN TblSupply ON CHARINDEX(CAST(TblSupply.IDSupply AS VARCHAR(10)), TblService.UsedSupplyIDs) > 0
GROUP BY TblPatientService.IDPatientService;
替换 XML 东西!
评论太长了。
我强烈建议修复您的数据模型。在数据库列中存储分隔列表是一种典型的设计反模式,它会以不同的方式适得其反(复杂性、效率、维护、数据完整性)。您可以查看 this famous SO question 了解更多详情。
举个例子:对于一些长度超过一位数的供应 ID(通常 1 会匹配 10),您当前的加入条件不会达到您的预期。
您应该标准化您的模型并有一个单独的 table 来存储服务和用品之间的 N-M 关系,每行一个元组。