Sql server 2008 使用表值参数进行查询

Sql server 2008 使用表值参数进行查询,sql-server-2008,stored-procedures,table-valued-parameters,Sql Server 2008,Stored Procedures,Table Valued Parameters,我需要关于编写存储过程的帮助,它需要一个表值参数@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_KE

我需要关于编写存储过程的帮助,它需要一个表值参数@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)
)
@位置将至少包含一行。每行将有一个非空的CountryId,并且可能有一个非空的名称。 每行将有一个唯一的序号,第一个是0。@Locations中的CountryId和ResortName的组合将是唯一的

存储过程需要根据下表结构进行搜索


通过右键单击图像并查看图像或类似内容(取决于浏览器),可以更好地查看图像

这就是我被困的地方,sproc应该能够找到以下地方的旅游:

  • 巡回赛第一巡回酒店(序号0) 具有相同的CountryId(和名称) 如有规定)第1行的 @位置(序号0)
  • 如果@Locations有>1行, 这次旅行必须有额外的费用 旅游酒店,所有这些都必须在 这些剩余@Locations行的剩余CountryID(和名称,如果指定)
编辑这是我根据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匹配,对吗?此外,@位置可能不包含其他旅游酒店?最后,如果CountryId从不为null,并且CountryId和RestorsName是唯一的,那么为什么不在表类型定义中包含它呢?恐怕还有更多问题。在@Locations表中可以有两行吗?一行用于,比如说,CountryID 12,名称为空,另一行用于CountryID,但名称为set?或者这两种类型的行永远不会混合?@Damien_不信者-不,序数>0不需要匹配。@Locations.CountryId中不包含其他变量。@Locations.CountryId在第一次传递到存储过程时将为null,我将只读输入参数复制到一个新变量,并在解决此问题之前填充该变量。我在这里展示它并不是为了简化事情,但是@Locations实际上有一个第四列,CountryName,客户端ASP.NET代码填充它,我用它来计算CountryId——一切正常。此外,同一个CountryId永远不会以null和非null名称传入。谢谢谢谢,我会尽快回到我的开发电脑上试试。谢谢,很接近了。我不得不把它改成旅游团。我现在能看到的唯一问题是,当我通过一行@Locations时,同时指定了CountryId和ResortName,不想要的旅游会被退回,而在同一个国家的其他度假酒店会有额外的酒店。e、 g.我搜索阿联酋+迪拜,但找到了阿联酋+迪拜+阿布扎比的旅游线路,但我只想要阿联酋+迪拜。@antmx我删除了与HAVING子句不同的内容。看看这是否对您有效。这似乎更好,但当我搜索阿联酋+迪拜+马来西亚+NULL时,我看到返回的旅游团在迪拜只有一家TourHotel,在马来西亚没有。再次感谢,我非常感谢您坚持这一点,但现在最后一行“WHERE M.Ordinal=0”导致错误“关键字WHERE附近的语法不正确”。另外,为了澄清,只需要@Locations序号0匹配TourHotel序号0,任何其他行都必须匹配,但不一定在同一序号。如果方便的话,如果您运行的是SQL Server 2008,我可以压缩数据库以便下载,或者我可以安排您登录我的数据库。嘿,您已经帮我解决了这个问题。非常感谢你。这是一份很棒的圣诞礼物,因为我已经坚持了好几天了。根据您上次的代码片段,我已经能够在我的第一篇文章中使用这些代码了。@antmx很高兴我能提供帮助。:-)
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)
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