【问题标题】:Search across multiple Price Ranges跨多个价格范围搜索
【发布时间】:2025-12-05 11:40:01
【问题描述】:

我们最近将一个旧的存储过程从动态 SQL 转换为直接 SQL。它是一个搜索引擎,我们让用户输入值字符串。

所以他们可能想要搜索多个订单号,以便他们输入

111,222-3,444-0

我们将该字符串处理成表值中的行,然后将该表加入我们的主订单表以返回这些行。

问题是他们拥有的选择之一是在多个价格范围内进行搜索。所以他们会选择 Invoice Totals 选项并输入

10-25,100-125,200-300

他们要求的是退回总发票金额在 10 美元到 25 美元之间或 100 美元到 125 美元之间或 200 美元到 300 美元之间的订单。

我不确定如何处理。当他们搜索字符串文本时,我们只需将列表解析为 FORMSOF(INFLECTIONAL 语句,我们将这些语句传递给 FTI 的 CONTAINSTABLE 调用。

任何建议从

10-25,100-125,200-300

WHERE InvoiceTotal BETWEEN  10 AND  25
   OR InvoiceTotal BETWEEN 100 and 125
   OR InvoiceTotal BETWEEN 200 and 300

或者,在不使用动态 SQL 的情况下功能相似。

【问题讨论】:

  • 重新设计用户界面以提供多个输入字段而不是强制后端支持输入的变化可能是最简单的
  • 可以使用几个字符串拆分函数来完成(不幸的是,不是内置函数,因为您需要在第二次拆分中保留顺序),但我怀疑更容易做的事情是使用动态 SQL,或者如果可能,更改存储过程以接受包含 FromTo 列的行的表值参数。

标签: tsql sql-server-2017


【解决方案1】:

您可以结合使用交叉应用和 sql server sting splitter 功能来根据用户的条件过滤您的数据。下面的例子演示了这个概念:

DECLARE @filter NVARCHAR(1000) = '10-25,100-125,500,200-300';

;WITH CTE_RangeComparisons
AS
(
    -- Use string split function to get input ranges
    SELECT      [value]
                ,(
                    -- If string contain the ‘-‘ character then we know we have a high limit and low limit specified otherwise we assume a single value.
                    CASE 
                        WHEN CHARINDEX('-',[value])  > 0 THEN CAST(LEFT([value], (CHARINDEX('-',[value]) - 1)) AS FLOAT) 
                        ELSE CAST([value] AS FLOAT)
                    END
                 ) AS LowRange
                ,(
                    CASE 
                        WHEN CHARINDEX('-',[value])  > 0 THEN CAST(RIGHT([value], LEN([value]) - (CHARINDEX('-',[value]))) AS FLOAT)
                        ELSE CAST([value] AS FLOAT)
                    END
                ) AS HighRange
    FROM        string_split(@filter, ',')
)
SELECT      D.*
FROM        [YourDataTable] D
CROSS APPLY (
                -- Use cross apply to filter data on the ranges identified.
                SELECT  1 [Match] -- Selected values here does not matter we are only interested in filtering the parent table.
                FROM    CTE_RangeComparisons R
                WHERE   D.InvoiceTotal >= R.LowRange AND D.InvoiceTotal <= R.HighRange
            ) Ranges

【讨论】: