【问题标题】:pull SQL results for search criteria conditions拉取搜索条件条件的 SQL 结果
【发布时间】:2012-01-04 17:34:10
【问题描述】:

请注意下面的 2 个查询。第一个对 4 个查询进行联合。我正在尝试根据以“@”为前缀的 3 个 SQL 变量为搜索条件编写 #2。因此,我们必须在搜索时考虑所有 3 个参数,而不是进行联合。如果任何参数/变量为 ''(或 NULL),则忽略该条件,但仍执行搜索。但所有字段都必须相互组合,才能在搜索结果中形成单行/记录。

如何重写 QUERY #2 以便它根据搜索条件(@companyName、@primaryPhone 和 @postalCode)提取结果?我认为 where 子句中的每个部分都必须有一些 OR 条件(因此它不会跳过 ''/NULL 搜索条件的行),但我很好奇这通常是如何完成的。 where 子句的 @primaryPhone 部分有点棘手,因为它同时查看电话和传真。

查询 #1

SELECT tempTable.optionValue, tempTable.optionText FROM (   

    SELECT 
        address.addressid AS 'optionValue', 
        address.name AS 'optionText'
    FROM 
        dbo.address 
    WHERE 
        addressid=1

    UNION

    -- Company Name internal partial match
    SELECT 
        address.addressid AS 'optionValue', 
        ('[' + CAST(address.addressid AS NVARCHAR(10)) + '] ' + ISNULL(address.name,'') + ', ' + ISNULL(address1,'') + ', ' + ISNULL(city,'') + ' ' + ISNULL(statecode,'') + ', ' + ISNULL(countrycode,'') + ' ' + ISNULL(postalcode,'')) AS 'optionText'
    FROM 
        dbo.[address]
        LEFT OUTER JOIN dbo.contact_address ON dbo.address.addressid = dbo.contact_address.addressid
        LEFT OUTER JOIN dbo.clientcontact ON dbo.contact_address.contactid = dbo.clientcontact.contactid
        LEFT OUTER JOIN dbo.client ON dbo.clientcontact.clientid = dbo.client.clientid
        LEFT OUTER JOIN dbo.contact ON dbo.contact_address.contactid = dbo.contact.contactid
    WHERE 
        client.name IS NOT NULL 
        AND client.name != ''
        AND @companyName != ''
        AND @companyName IS NOT NULL
        AND client.name LIKE '%' + @companyName + '%' 
        AND clientcontact.contacttypeid = 3 --primary contacts only

    UNION

    -- Primary Phone/Fax internal partial match     
    SELECT 
        address.addressid AS 'optionValue', 
        ('[' + CAST(address.addressid AS NVARCHAR(10)) + '] ' + ISNULL(address.name,'') + ', ' + ISNULL(address1,'') + ', ' + ISNULL(city,'') + ' ' + ISNULL(statecode,'') + ', ' + ISNULL(countrycode,'') + ' ' + ISNULL(postalcode,'')) AS 'optionText'
    FROM 
        dbo.[contact]
        LEFT OUTER JOIN dbo.clientcontact ON dbo.contact.contactid = dbo.clientcontact.contactid
        LEFT OUTER JOIN dbo.contact_address ON dbo.contact.contactid = dbo.contact_address.contactid
        LEFT OUTER JOIN dbo.address ON dbo.contact_address.addressid = dbo.address.addressid
    WHERE 
        (
            contact.dayphone IS NOT NULL 
            AND contact.dayphone != ''
            AND @primaryPhone != ''
            AND @primaryPhone IS NOT NULL
            AND contact.dayphone LIKE '%' + @primaryPhone + '%'
        )
        OR 
        (
            contact.fax IS NOT NULL 
            AND contact.fax != ''
            AND @primaryPhone != ''
            AND @primaryPhone IS NOT NULL
            AND contact.fax LIKE '%' + @primaryPhone + '%' 
        )
        AND clientcontact.contacttypeid = 3 --primary contacts only

    UNION

    SELECT 
        address.addressid AS 'optionValue', 
        ('[' + CAST(address.addressid AS NVARCHAR(10)) + '] ' + ISNULL(address.name,'') + ', ' + ISNULL(address1,'') + ', ' + ISNULL(city,'') + ' ' + ISNULL(statecode,'') + ', ' + ISNULL(countrycode,'') + ' ' + ISNULL(postalcode,'')) AS 'optionText'
    FROM 
        dbo.[contact]
        LEFT OUTER JOIN dbo.clientcontact ON dbo.contact.contactid = dbo.clientcontact.contactid
        LEFT OUTER JOIN dbo.contact_address ON dbo.contact.contactid = dbo.contact_address.contactid
        LEFT OUTER JOIN dbo.address ON dbo.contact_address.addressid = dbo.address.addressid
    WHERE 
        @postalCode != ''
        AND @postalCode IS NOT NULL
        AND address.postalcode LIKE @postalCode + '%'
        AND clientcontact.contacttypeid = 3 --primary contacts only

) AS tempTable

查询 #2(搜索)

SELECT tempTable.optionValue, tempTable.optionText FROM (   

    SELECT 
        address.addressid AS 'optionValue', 
        address.name AS 'optionText'
    FROM 
        dbo.address 
    WHERE 
        addressid=1

    UNION

    SELECT 
        address.addressid AS 'optionValue', 
        ('[' + CAST(address.addressid AS NVARCHAR(10)) + '] ' + ISNULL(address.name,'') + ', ' + ISNULL(address1,'') + ', ' + ISNULL(city,'') + ' ' + ISNULL(statecode,'') + ', ' + ISNULL(countrycode,'') + ' ' + ISNULL(postalcode,'')) AS 'optionText'
    FROM 
        dbo.[address]
        LEFT OUTER JOIN dbo.contact_address ON dbo.address.addressid = dbo.contact_address.addressid
        LEFT OUTER JOIN dbo.clientcontact ON dbo.contact_address.contactid = dbo.clientcontact.contactid
        LEFT OUTER JOIN dbo.client ON dbo.clientcontact.clientid = dbo.client.clientid
        LEFT OUTER JOIN dbo.contact ON dbo.contact_address.contactid = dbo.contact.contactid
    WHERE 
        (
            client.name IS NOT NULL 
            AND client.name != ''
            AND @companyName != ''
            AND @companyName IS NOT NULL
            AND client.name LIKE '%' + @companyName + '%' 
        )
        AND 
        (
            (
                contact.dayphone IS NOT NULL 
                AND contact.dayphone != ''
                AND @primaryPhone != ''
                AND @primaryPhone IS NOT NULL
                AND contact.dayphone LIKE '%' + @primaryPhone + '%'
            )
            OR 
            (
                contact.fax IS NOT NULL 
                AND contact.fax != ''
                AND @primaryPhone != ''
                AND @primaryPhone IS NOT NULL
                AND contact.fax LIKE '%' + @primaryPhone + '%' 
            )
        )
        AND
        (
            @postalCode != ''
            AND @postalCode IS NOT NULL
            AND address.postalcode LIKE @postalCode + '%'
        )                       
        AND clientcontact.contacttypeid = 3 --primary contacts only

) AS tempTable

【问题讨论】:

  • 如果字段为 NULL,由于 LEFT JOIN,是否应该忽略该条件? (或改写,如果该字段为NULL,则从不排除。)
  • 是的,如果 ''/NULL 则忽略该条件,但如果它是 ''/NULL 则不要排除该行
  • 我的意思是写“是的,如果 ''(或 NULL),则忽略该搜索条件,但如果搜索条件 ''(或 NULL),请不要排除该行”......你是询问数据库中记录中的字段,而不是搜索条件..在这种情况下,如果记录/行字段为''(或NULL),我想排除这些记录......所以我不想要所有您修改后的答案中的那些 OR 条件@Dems。

标签: sql sql-server-2008 tsql search


【解决方案1】:

编辑新规则

                     |  Field = '' or NULL  |  Field != '' or NULL
---------------------+----------------------+-----------------------
Param  = '' or NULL  |    Include Record    |    Include Record
---------------------+----------------------+-----------------------
Param != '' or NULL  |    Exclude Record    |   Include if Match


WHERE 
    (
           @companyName = ''
        OR @companyName IS NULL
        OR client.name LIKE '%' + @companyName + '%' 
    )
    AND 
    (
        (
               @primaryPhone = ''
            OR @primaryPhone IS NULL
            OR contact.dayphone LIKE '%' + @primaryPhone + '%'
        )
        OR 
        (
               @primaryPhone = ''
            OR @primaryPhone IS NULL
            OR contact.fax LIKE '%' + @primaryPhone + '%' 
        )
    )
    AND
    (
           @postalCode = ''
        OR @postalCode IS NULL
        OR address.postalcode LIKE @postalCode + '%'
    )                       
    AND clientcontact.contacttypeid = 3 --primary contacts only

【讨论】:

  • 第一个 (@companyName) 和第二个 (@primaryPhone) 条件是部分内部匹配.. 第三个 (@postalCode) 是一个开头(这就是为什么我只有在末尾有 % LIKE 条件)
  • @MacGyver - 我以为你可以自己进行这些修改 :)
  • 查看我的评论问题
  • "1.如果字段为NULL或'',不排除"...应该写成"1.如果字段为NULL或'',排除"
  • 谢谢.. 在我的第一个查询中,我正在检查数据库字段是否为 != '' 和 NOT NULL ...当我重新编写它时,这让我感到困惑。 +1
【解决方案2】:
@postalCode != ''
            AND @postalCode IS NOT NULL
            AND address.postalcode LIKE @postalCode + '%'

可以写成

AND address.postalcode LIKE IsNull(@postalCode, '') + '%'

根本不需要测试你有一个变量,sql会在执行时忽略它='%'

根据我的经验,大量 OR 确实会减慢查询速度(但还是要查看 exe 计划)。这对眼睛来说也容易多了。

【讨论】:

  • sql will ignore it in the execution when = '%' - 这并不总是正确的。如果这是用于存储过程或参数化查询,则执行 plan 将已经形成以满足所有参数的比较。这包括需要哪个索引和排序,无论参数中的值如何。不过,对速度的谨慎是有道理的。但由于一些或许多比较可能是LIKE '%xxx%',这无论如何都是表扫描。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多