首页 > 解决方案 > 使用 udt 忽略搜索查询中的 null

问题描述

我正在研究过滤器功能,但我正在努力使用 Sql。

我有这个逻辑的过程。

    RIGHT JOIN @filterQuery as fq
        ON (fq.Bpm = c.BPM OR fq.Bpm IS NULL) 
        AND (fq.Price  >= c.Price OR fq.Price IS NULL)
        AND (fq.GenreTypeId = g.Id OR fq.GenreTypeId IS NULL)
        AND (fq.KeyTypeId = k.Id OR fq.KeyTypeId IS NULL)
        AND (fq.TrackTypeId = t.Id OR fq.TrackTypeId IS NULL)

我的测试代码看起来像这样

DECLARE     @filters AS dbo.FilterTable
                    ,@PageIndex int = 0
                    ,@PageSize int = 10


        INSERT INTO @filters (Bpm,Price,GenreTypeId,KeyTypeId,TrackTypeId)
                
        VALUES (126,null,null,null,null),(76,null,null,null,2)

        EXECUTE dbo.PROC     @filters
                            ,@PageIndex
                            ,@PageSize

现在我的问题是,当我运行我的代码时,我的结果集看起来像这样。

Bpm  Price  GenreTypeId  KeyTypeId  TrackTypeId
126  5.99       1            1           1 
126  4.99       1            1           1

这是有道理的,因为没有BPM 76TrackTypeId 2的记录,但是因为BPM 126的第一组值在TrackTypeId处为 NULL,所以它不会从第二组值中过滤TrackTypeId 2。

我需要我的结果集为,因为数据库中没有任何TrackTypeId 2的记录。这可能吗?

编辑:我希望我的结果集为空,因为没有 trackTypeId 2 的数据。但目前它给了我所有 126 BPM,因为这个特定过滤器的 trackTypeId 为空。

标签: sqlsql-servertsqlsearchfilter

解决方案


从您尝试实现的逻辑来看,您需要的是每个过滤列都有一个单独的表类型。您还应该具有以下样式的逻辑

WHERE (NOT EXISTS (SELECT 1 FROM @columnFilters) OR column IN (SELECT * FROM @columnFilters))

为了这种目的,我通常在我的数据库中保留一些标准的单列表类型的各种数据类型。

WHERE (NOT EXISTS (SELECT 1 FROM @Bpm) OR
    c.Bpm IN (SELECT * FROM @Bpm))
  AND (c.Price >= @Price OR @Price IS NULL)
  AND (NOT EXISTS (SELECT 1 FROM @GenreTypeId) OR
    g.Id IN (SELECT * FROM @GenreTypeId))
  AND (NOT EXISTS (SELECT 1 FROM @KeyTypeId) OR
    k.Id IN (SELECT * FROM @KeyTypeId))
  AND (NOT EXISTS (SELECT 1 FROM @TrackTypeId) OR
    t.Id IN (SELECT * FROM @TrackTypeId))

请注意使用标量变量 for @Price,因为您可以输入所需的最小值,因为条件是不等式>=

如果您确实也想为此使用表格,则可以这样做:

(NOT EXISTS (SELECT 1 FROM @Price) OR
    c.Price >= ANY(SELECT * FROM @GenreTypeId))

OPTION(RECOMPILE)如果您尝试访问索引,我强烈建议您查看此类查询的任何一个或动态 SQL。


推荐阅读