【问题标题】:FOR XML PATH produces only first itemFOR XML PATH 只产生第一项
【发布时间】:2022-01-03 01:23:20
【问题描述】:

我有两张桌子:Reservations 和 ReservationNights(每个预订都有很多晚)。

在存储过程中,我有一个如下所示的变量:@roomTypeList = '2;3;4;5;' -> 它是 RoomUseIds 的列表。

我只需要显示具有这些 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)) + ';%')))

【问题讨论】:

  • 请将示例数据复制为文本而不是图像,以便我们进行复制和粘贴。您还应该提供预期的结果,以便我们帮助您进行查询。
  • WHERE 中有一个FOR XML PATh 感觉就像是一个XY Problem。为什么首先需要与WHERE 中的分隔字符串进行比较?
  • 提问时,您需要提供minimal reproducible example: (1) DDL 和样本数据填充,即 CREATE 表和 INSERT T-SQL 语句。 (2) 你需要做什么,即逻辑和你的代码尝试在 T-SQL 中实现它。 (3) 期望的输出,基于上述#1 中的样本数据。 (4) 您的 SQL Server 版本 (SELECT @@version;)。

标签: sql sql-server database tsql stored-procedures


【解决方案1】:

您的关键问题是缺乏规范化。如果您有列表,请将其存储为列表。

所以你需要一个表变量或表值参数。 在紧要关头,您可以拆分现有字符串,但最好首先将数据采用正确的格式。

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 合并到上述查询中,而不是尝试构造等效的聚合字符串。

【讨论】:

    【解决方案2】:

    我建议另一种方法:确保您的变量在每个值之前和之后都有一个分隔符(例如:';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)) + ';'
        )
    )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-08-13
      • 1970-01-01
      • 1970-01-01
      • 2020-09-25
      • 2018-06-17
      • 1970-01-01
      • 2011-09-21
      • 1970-01-01
      相关资源
      最近更新 更多