FOR XML PATH 只产生第一项
FOR XML PATH produces only first item
我有两个表:Reservations 和 ReservationNights(每个预订都有很多晚)。
在存储过程中,我有一个如下所示的变量:@roomTypeList = '2;3;4;5;'
-> 它是一个 RoomUseId 列表。
我只需要显示具有其中一个 ID 的预订晚数的预订(在此示例中,它应该只显示预订 14105,因为存在 RoomUseId = 3 和 '2;3;4;5;'
变量包含 3.
我试过使用类似的方法,但效果不佳 - 有时应该显示多个预订时它只显示 1 个预订,通常它什么都不显示。
SELECT DISTINCT r.Id, r.BookingStatus, r.CurrencyId
FROM Reservations r
--JOIN ReservationNights rn ON rn.ReservationId = r.Id
WHERE
(@roomTypeListLocal IS NULL OR (@roomTypeListLocal LIKE ('%' + CAST((SELECT STUFF((SELECT ';' + CAST(rn.RoomUseId as nvarchar(MAX))
FROM ReservationNights rn
WHERE rn.ReservationId = r.Id AND rn.RoomUseId IS NOT NULL
FOR XML PATH('')), 1, 1, '')) as nvarchar(MAX)) + ';%')))
我建议另一种方法:确保变量在每个值前后都有分隔符(例如:';2;3;4;5;'
),并使用 EXISTS
查询:
SELECT DISTINCT r.Id, r.BookingStatus, r.CurrencyId
FROM Reservations r
WHERE
(
@roomTypeListLocal IS NULL
OR
EXISTS
(
SELECT 1
FROM ReservationNights rn
WHERE rn.ReservationId = r.Id
AND rn.RoomUseId IS NOT NULL
AND @roomTypeListLocal LIKE ';' + CAST(rn.RoomUseId As varchar(10)) + ';'
)
)
你的关键问题是缺乏规范化。如果您有列表,请将其存储为列表。
因此您需要一个 table 变量或 Table 值参数。 在紧要关头,您可以拆分现有的字符串,但最好首先让数据采用正确的格式。
DECLARE @roomTypeList TABLE (roomType int PRIMARY KEY);
INSERT @roomTypeList (roomType)
SELECT *
FROM STRING_SPLIT(@roomTypeListLocal, ';');
SELECT
r.Id,
r.BookingStatus,
r.CurrencyId
FROM Reservations r
WHERE
@roomTypeListLocal IS NULL
OR EXISTS (SELECT 1
FROM ReservationNights rn
JOIN @roomTypeList rl ON rl.roomType = rn.RoomUseId
WHERE rn.ReservationId = r.Id
);
如果您真的想要坚持使用逗号分隔的列表,您可以将 STRING_SPLIT
合并到上述查询中,而不是尝试构建等效的聚合字符串.
我有两个表:Reservations 和 ReservationNights(每个预订都有很多晚)。
在存储过程中,我有一个如下所示的变量:@roomTypeList = '2;3;4;5;'
-> 它是一个 RoomUseId 列表。
我只需要显示具有其中一个 ID 的预订晚数的预订(在此示例中,它应该只显示预订 14105,因为存在 RoomUseId = 3 和 '2;3;4;5;'
变量包含 3.
我试过使用类似的方法,但效果不佳 - 有时应该显示多个预订时它只显示 1 个预订,通常它什么都不显示。
SELECT DISTINCT r.Id, r.BookingStatus, r.CurrencyId
FROM Reservations r
--JOIN ReservationNights rn ON rn.ReservationId = r.Id
WHERE
(@roomTypeListLocal IS NULL OR (@roomTypeListLocal LIKE ('%' + CAST((SELECT STUFF((SELECT ';' + CAST(rn.RoomUseId as nvarchar(MAX))
FROM ReservationNights rn
WHERE rn.ReservationId = r.Id AND rn.RoomUseId IS NOT NULL
FOR XML PATH('')), 1, 1, '')) as nvarchar(MAX)) + ';%')))
我建议另一种方法:确保变量在每个值前后都有分隔符(例如:';2;3;4;5;'
),并使用 EXISTS
查询:
SELECT DISTINCT r.Id, r.BookingStatus, r.CurrencyId
FROM Reservations r
WHERE
(
@roomTypeListLocal IS NULL
OR
EXISTS
(
SELECT 1
FROM ReservationNights rn
WHERE rn.ReservationId = r.Id
AND rn.RoomUseId IS NOT NULL
AND @roomTypeListLocal LIKE ';' + CAST(rn.RoomUseId As varchar(10)) + ';'
)
)
你的关键问题是缺乏规范化。如果您有列表,请将其存储为列表。
因此您需要一个 table 变量或 Table 值参数。 在紧要关头,您可以拆分现有的字符串,但最好首先让数据采用正确的格式。
DECLARE @roomTypeList TABLE (roomType int PRIMARY KEY);
INSERT @roomTypeList (roomType)
SELECT *
FROM STRING_SPLIT(@roomTypeListLocal, ';');
SELECT
r.Id,
r.BookingStatus,
r.CurrencyId
FROM Reservations r
WHERE
@roomTypeListLocal IS NULL
OR EXISTS (SELECT 1
FROM ReservationNights rn
JOIN @roomTypeList rl ON rl.roomType = rn.RoomUseId
WHERE rn.ReservationId = r.Id
);
如果您真的想要坚持使用逗号分隔的列表,您可以将 STRING_SPLIT
合并到上述查询中,而不是尝试构建等效的聚合字符串.