2012-01-04 54 views
1

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

如何重写QUERY#2,以便根据搜索条件(@companyName,@primaryPhone和@postalCode)提取结果?我认为where子句中的每个部分都必须有一些OR条件(所以它不会跳过'/ NULL搜索条件的行),但我很好奇这是如何实现的。 where子句的@primaryPhone部分有点麻烦,因为它看起来既有电话又有传真。

QUERY#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 

QUERY#2(SEARCH)

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 
+0

如果一个字段为NULL,由于LEFT JOIN,应该忽略该条件吗? (或重写,如果该字段为NULL,则永远不会排除) – MatBailie 2012-01-04 17:42:22

+0

是的,如果为''/ NULL,则忽略该条件,但如果是'/ NULL则不排除该行 – MacGyver 2012-01-04 17:44:50

+0

我的意思是写“yes,ignore如果搜索条件为''(或NULL),但不排除该行,如果搜索条件''(或NULL)“... ...你询问数据库记录中的字段而不是搜索条件。在这种情况下,如果记录/行字段是''(或NULL),我想排除这些记录...所以我不希望修改后的答案@Dems中包含所有这些OR条件。 – MacGyver 2012-01-04 17:54:12

回答

1

EDIT新规则

     | 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 
+0

第一个(@companyName)和第二个(@primaryPhone)条件是部分内部匹配..第三个(@postalCode)是一个开始-with(这就是为什么我只有在LIKE条件结束时才有%) – MacGyver 2012-01-04 17:40:33

+0

@MacGyver - 我认为你可以自己做那些修改:) – MatBailie 2012-01-04 17:41:28

+0

请参阅我的问题 – MacGyver 2012-01-04 17:55:44

0
@postalCode != '' 
      AND @postalCode IS NOT NULL 
      AND address.postalcode LIKE @postalCode + '%' 

可以写成

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

不需要测试,你有一个变量可言,SQL会忽略它在执行时= '%'

根据我的经验,大量ORs会真正减慢查询速度(但无论如何看看exe计划)。这是一个更容易在眼睛上也是伊莫。

+0

当='%''时,sql会在执行时忽略它 - 这并不总是对的。如果这是针对存储过程或参数化查询,则执行***计划***将已经形成以迎合所有参数的比较。这包括哪些索引和排序是必要的,而不管参数中的值如何。但速度的谨慎是有保证的。但因为一些或许多比较可能是'LIKE'%xxx%''这将以任何方式进行表格扫描。 – MatBailie 2012-01-04 18:05:05