【问题标题】:Querying using table-valued parameter使用表值参数查询
【发布时间】:2010-12-22 00:57:09
【问题描述】:

我需要帮助编写一个sproc,它需要一个表值参数@Locations,其类型定义如下:

CREATE TYPE [dbo].[tvpLocation] AS TABLE(
    [CountryId] [int] NULL,
    [ResortName] [nvarchar](100) NULL,
    [Ordinal] [int] NOT NULL,
    PRIMARY KEY CLUSTERED 
(
    [Ordinal] ASC
)WITH (IGNORE_DUP_KEY = OFF)
)

@Locations 将包含至少 1 行。每行将有一个非空的 CountryId,并且可能有一个非空的 ResortName。 每行都有一个唯一的序数,第一个是 0。@Locations 中 CountryId 和 ResortName 的组合将是唯一的。

sproc 需要搜索下面的表结构。

可以通过右键单击图像并查看图像或类似的方式更好地查看图像,具体取决于您的浏览器。

现在这是我卡住的地方,sproc 应该能够找到 Tours 的位置:

  • The Tour's 1st TourHotel (Ordinal 0) 具有相同的 CountryId(和 ResortName 如果指定)的第一行 @Locations(序号 0)。
  • 如果@Locations 有 > 1 行, 巡回赛必须有额外的 TourHotels,所有这些都必须在 这些剩余的 @Locations 行的剩余 CountryIds(和 ResortNames,如果指定)。

编辑 这是我最终使用的代码,基于 Anthony Faull 的建议。非常感谢安东尼:

select distinct T.Id
from tblTour T
join tblTourHotel TH on TH.TourId = T.Id
join tblHotel H ON H.Id = TH.HotelId
JOIN @Locations L ON
    (
        (
            L.Ordinal = 0
            AND TH.Ordinal = 0
        )
        OR
        (
            L.Ordinal > 0
            AND TH.Ordinal > 0
        )
    )
    AND L.CountryId = H.CountryId
    AND
    (
        L.ResortName = H.ResortName
        OR L.ResortName IS NULL
    )
cross apply( select COUNT(TH2.Id) AS [Count] FROM tblTourHotel TH2 where TH2.TourId = TH.TourId ) TourHotelCount
where
TourHotelCount.[Count] = @LocationCount
group by T.Id, T.TourRef, T.Description, T.DepartureDate, T.NumNights, T.DepartureAirportId, T.DestinationAirportId, T.AirlineId, T.FEPrice
having COUNT(distinct TH.Id) = @LocationCount

【问题讨论】:

  • 我不知道其他人,但我看不懂。
  • 可以通过右键单击图像并查看图像或类似的方式更好地查看图像,具体取决于您的浏览器。
  • 我是否正确地说序数不需要匹配序数> 0?此外,@Locations 中可能不包含其他 TourHotels?最后,如果 CountryId 永远不会为 null,并且 CountryId 和 ResortName 是唯一的,为什么不包含在表类型定义中?
  • 恐怕还有更多问题。 @Locations 表中是否可以有两行,其中一行用于 CountryID 12 且度假村名称为空,另一行也用于 CountryID 但设置了度假村名称?或者这两种类型的行永远不会混合?
  • @Damien_The_Unbeliever - 不,序数 > 0 不需要匹配。 @Locations.CountryId 中不能有其他 TourHotels 不包含在第一次传递到存储过程中时将为空,我将只读输入参数复制到一个新变量并在我遇到这个问题之前填充它。我没有在这里展示它以试图简化事情,但@Locations 实际上有第四列 CountryName,客户端 ASP.NET 代码填充它,我用它来计算 CountryId - 一切正常。此外,永远不会使用 null 和非 null 的 ResortName 传入相同的 CountryId。谢谢

标签: sql-server-2008 stored-procedures table-valued-parameters


【解决方案1】:
WITH Matches AS
(
    SELECT TH.TourId, TH.Ordinal
    FROM dbo.tblTourHotel TH
    WHERE EXISTS
    (
        SELECT 1
        FROM dbo.tblHotel H
        JOIN @Locations L ON
            (
                (
                    L.Ordinal = 0
                    AND TH.Ordinal = 0
                )
                OR
                (
                    L.Ordinal > 0
                    AND TH.Ordinal > 0
                )
            )
            AND L.CountryId = H.CountryId
            AND
            (
                L.ResortName = H.ResortName
                OR L.ResortName IS NULL
            )
        WHERE H.Id = TH.HotelId
    )
)
SELECT M.TourId
FROM Matches M
WHERE
(
    NOT EXISTS
    (
        SELECT 1
        FROM @Locations L
        WHERE L.Ordinal > 0
    )
    OR NOT EXISTS
    (
        SELECT 1
        FROM dbo.tblTourHotel TH
        WHERE TH.Ordinal > 0
        AND NOT EXISTS
        (
            SELECT 1
            FROM Matches M
            WHERE M.Ordinal = TH.Ordinal
            AND M.TourId = TH.TourId
        )
    )
)
WHERE M.Ordinal = 0

【讨论】:

  • 再次感谢,我非常感谢您坚持这样做,但现在最后一行“WHERE M.Ordinal = 0”导致错误“关键字 WHERE 附近的语法不正确”。此外,为了澄清,@Locations Ordinal 0 只需要匹配 TourHotel Ordinal 0,任何其他行必须匹配,但不一定在同一个 Ordinal。如果您运行的是 SQL Server 2008,我可以将数据库压缩以供下载,或者我可以安排您登录到我的数据库。
  • 嘿,你帮我解决了这个问题。非常感谢。这是一份很棒的圣诞礼物,因为我已经坚持了几天了。根据你上一个代码 sn-p,我已经能够在我的第一篇文章中得到这个工作,代码。
  • @antmx 很高兴我能帮上忙。 :-)
【解决方案2】:
SELECT TH.TourId
FROM dbo.tblTourHotel TH
JOIN dbo.tblHotel H on H.Id = TH.HotelId
LEFT JOIN @Locations L
    ON SIGN(L.Ordinal) = SIGN(TH.Ordinal) 
    AND L.CountryId = H.CountryId 
    AND (L.ResortName = H.ResortName OR L.ResortName IS NULL)
GROUP BY TH.TourId
HAVING COUNT(H.CountryId) = COUNT(L.CountryId)

【讨论】:

  • 谢谢,我会尽快回到我的开发计算机上尝试。
  • 谢谢,这已经很接近了。我不得不将其调整为 GROUP BY TH.TourID。我现在可以看到的唯一问题是,当我传入带有单行的 @Locations 时,其中指定了 CountryId 和 ResortName,返回不需要的旅游,这些旅游在同一国家的其他度假村有其他酒店。例如我搜索阿联酋 + 迪拜,但找到了与阿联酋 + 迪拜 + 阿布扎比的旅游,但我只想要阿联酋 + 迪拜。
  • @antmx 我已经从 HAVING 子句中删除了 DISTINCT。看看这是否适合你。
  • 这似乎更好,但是当我搜索UAE+Dubai plus Malaysia+NULL 时,我看到返回的Tours 在迪拜只有1 家TourHotel,在马来西亚没有。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-22
  • 1970-01-01
  • 2020-11-30
  • 1970-01-01
相关资源
最近更新 更多