SQL:根据用户选择应用过滤器,过滤器应匹配所有值

时间:2016-05-29 15:53:32

标签: sql sql-server sql-server-2008

我有一个场景,我必须根据用户选择应用过滤器,过滤器应匹配所有值。 例如:如果用户对酒店设施应用过滤器,则应过滤符合用户选择的所有设施的酒店。

HotelID AmenitiesID

Create PROCEDURE [dbo].[usp_GetHotelListing]
@HotelID INT = 1,
@Amenities varchar(50) = '1,3'
AS
BEGIN
select  * from DTHotelAmenities where HotelID = @HotelID and <Searching For Condition>
END
{{1}}

3 个答案:

答案 0 :(得分:1)

&#34; [...]它应该过滤匹配所有用户选择的设施的酒店。&#34;

这是relational division

第一个解决方案(我发送设施清单)我会使用TVP

CREATE TYPE dbo.IntArray AS TABLE ( 
    -- NULLs and duplicated are disallowed.
    IntValue INT NOT NULL PRIMARY KEY 
);
GO

create procedure [dbo].[usp_GetHotelListing]
@HotelID INT = 1,
@Amenities IntArray READONLY
AS
begin
    select  ha.HotelID  
    from DTHotelAmenities ha 
    where HotelID = @HotelID 
    and exists (select * from @Amenities a where ha.AmenitiesID = a.IntValue)
    group by ha.HotelID 
    -- Use distinct if there is not UNIQUE index / constraint defined on (HotelID, AmenitiesID)
    having count(/*distinct*/ ha.AmenitiesID) = (select count(*) from @Amenities)
end

第二个解决方案使用XML发送值列表:

create procedure [dbo].[usp_GetHotelListing]
@HotelID INT = 1,
@Amenities XML = N'<r><i value="1"><i value="3"></r>'
AS
begin
    create table #Amenities (AmenitiesID INT)
    insert #Amenities (AmenitiesID)
    select b.XmlCol.value('(@AmenitiesID)[1]', 'INT')
    from (select @Amenities) a(XmlCol)
    cross apply a.XmlCol.nodes('r/i') b(XmlCol)

    select  ha.HotelID  
    from DTHotelAmenities ha 
    where HotelID = @HotelID 
    and exists (select * from #Amenities a where ha.AmenitiesID = a.IntValue)
    group by ha.HotelID 
    -- 1) Use distinct if there is not UNIQUE index / constraint defined on (HotelID, AmenitiesID)
    -- 2) Use "count(distinct IntValue)" if @Amenities param could contain duplicated values
    having count(/*distinct*/ ha.AmenitiesID) = (select count(/*distinct*/ IntValue) from #Amenities)
end

答案 1 :(得分:0)

动态查询版本:

Create PROCEDURE [dbo].[usp_GetHotelListing]
@HotelID INT = 1,
@Amenities varchar(50) = '1,3'
AS
BEGIN

    declare @sql nvarchar(max) = 
     'select  * from DTHotelAmenities where HotelID = ' + 
      cast(@HotelID as nvarchar(max)) + 
      ' and AmenitiesID in(' + @Amenities + ')'

     exec(@sql)

END

一般要注意sql注入威胁的可能性。您可能需要查看sp_executesql替代方案。

答案 2 :(得分:0)

也许就像....

Create PROCEDURE [dbo].[usp_GetHotelListing]
@HotelID INT = 1,
@Amenities varchar(50) = '1,3'
AS
BEGIN
  SET NOCOUNT ON;
  Declare @xml XML;
  Declare @t table (ID INT);

  SET @xml = '<root><x>' +  REPLACE(@Amenities , ',' , '</x><x>')  + '</x></root>'

INSERT INTO @t(ID)
Select r.value('.', 'VARCHAR(max)') value
FROM @xml.nodes('//root/x') as records(r)

select  o.* 
from DTHotelAmenities o
INNER JOIN @t t ON t.ID = o.AmenitiesID
where o.HotelID = @HotelID

END