具有动态搜索条件的SQL搜索查询

时间:2015-06-05 07:26:03

标签: sql sql-server sql-server-2012

我有一个旧的动态SQL查询,如下所示,where子句中的条件是根据搜索文本动态追加的。

  

示例1 :搜索字符串' AMX AC-DIN-CS3支架'

SELECT * FROM Tx_Product
Where Fk_CompanyId=1   
and  (ModelNumber like '%AMX%' or Manufacturer like '%AMX%' or Category like '%AMX%' or [Description] like '%AMX%')
and  (ModelNumber like '%AC-DIN-CS3%' or Manufacturer like '%AC-DIN-CS3%' or Category like '%AC-DIN-CS3%' or [Description] like '%AC-DIN-CS3%')
and  (ModelNumber like '%Bracket%' or Manufacturer like '%Bracket%' or Category like '%Bracket%' or [Description] like '%Bracket%')

这里有3个And子句,因为搜索字符串中有3个部分(以空格分隔(AMX,AC-DIN-CSS3和Bracket)。

  

示例2 :搜索字符串' AMX AC-DIN-CS3'

SELECT * FROM Tx_Product
Where Fk_CompanyId=1   
and  (ModelNumber like '%AMX%' or Manufacturer like '%AMX%' or Category like '%AMX%' or [Description] like '%AMX%')
and  (ModelNumber like '%AC-DIN-CS3%' or Manufacturer like '%AC-DIN-CS3%' or Category like '%AC-DIN-CS3%' or [Description] like '%AC-DIN-CS3%')    

这里有2个和子句,因为搜索字符串中有2个部分(AMX,AC-DIN-CS3)。

我想摆脱动态sql 并创建一个单独的查询,根据搜索字符串得到与上面相同的结果,但我得到的结果不同。

  

相当于示例1 但是有额外的结果

DECLARE @SearchString NVARCHAR(MAX) = 'AMX AC-DIN-CS3 Bracket'

SELECT DISTINCT Prod.* FROM Tx_Product Prod
CROSS APPLY (SELECT DISTINCT part FROM [dbo].[SplitString] (@SearchString,'')) AS SearchParts
Where  Fk_CompanyId = 1
AND (ModelNumber LIKE SearchParts.part OR Prod.Manufacturer LIKE SearchParts.part 
OR Prod.Category LIKE SearchParts.part OR Prod.[Description] LIKE SearchParts.part)

在这里,我得到额外的记录,如(所有产品与制造商' AMX' 以及所有产品与ModelNumber ' AC-DIN-CS3&# 39;

问题我希望根据搜索字符串帮助构建单个查询(示例1的等式,这将给出与示例1相同的结果)。  因此,这个带有调整的新Equiv查询将满足这两个示例。

我已更新SQL Fidddle中的架构。

先谢谢你的帮助。

注意: [dbo].[SplitString]以字符串形式返回字符串的distint部分。 这里'AMX-AC-DIN-CS3'将返回

'AMX'
'AC-DIN-CS3'

3 个答案:

答案 0 :(得分:3)

问题是部分匹配。

尝试以下查询。

每个关键字的匹配都会获得其编号,如果产品最大数量等于关键字的总数,则匹配已满并且应选择产品

select * from 
(
SELECT 
    DISTINCT Prod.* 
    ,row_number() over 
        (partition by Pk_ProductID
        order by SearchParts.part) as num
FROM Tx_Product Prod
CROSS APPLY (SELECT DISTINCT '%'+part+'%' as part FROM [dbo].[SplitString] (@SearchString,'')) AS SearchParts
Where  Fk_CompanyId = 1
AND (ModelNumber LIKE SearchParts.part OR Prod.Manufacturer LIKE SearchParts.part 
OR Prod.Category LIKE SearchParts.part OR Prod.[Description] LIKE SearchParts.part)
) T
-- the number of last line for product
-- is equal to total count of keywords
where T.num = (SELECT count(DISTINCT part) FROM [dbo].[SplitString] (@SearchString,''))

答案 1 :(得分:2)

我更喜欢使用CTE来使查询文本更具可读性。

我认为表Tx_Product有一个主键ID

首先我们将@SearchString转换为表格。然后计算其中的行数以获得关键字的总数。

您希望找到包含所有给定关键字的产品。

对于每个关键字,我们使用CROSS APPLY来获取包含此关键字的产品ID列表。然后我们按ID分组以计算匹配数,并仅保留匹配数与关键字总数相同的ID。

最后,我们使用找到的ID从表中获取所有产品详细信息。

以下是基于您的SQL Fiddle

WITH
CTE_Parts
AS
(
    SELECT DISTINCT '%' + part + '%' AS Part
    FROM [dbo].[SplitString](@SearchString,'')
)
,CTE_PartCount
AS
(
    SELECT COUNT(*) AS PartCount
    FROM CTE_Parts
)
,CTE_ProductIDs
AS
(
    SELECT
        ID
    FROM
        CTE_Parts
        CROSS APPLY
        (
            SELECT ID
            FROM Tx_Product
            WHERE
                Fk_CompanyId = 1
                AND (ModelNumber LIKE CTE_Parts.Part
                    OR Manufacturer LIKE CTE_Parts.Part
                    OR Category LIKE CTE_Parts.Part
                    OR [Description] LIKE CTE_Parts.Part)
        ) AS CA
    GROUP BY ID
    HAVING COUNT(*) = (SELECT PartCount FROM CTE_PartCount)
)
SELECT
    Tx_Product.*
FROM
    CTE_ProductIDs
    INNER JOIN Tx_Product ON Tx_Product.ID = CTE_ProductIDs.ID

答案 2 :(得分:1)

请试试这个:

$(".preview-audio").insertAfter($(".foo"));