SQL Server 2008 - 使用表Join的关键字搜索

时间:2012-07-03 14:34:32

标签: sql-server sql-server-2008 stored-procedures join

好的,我创建了一个存储过程,其中包括搜索特定关键字的5列。为了实现这一点,我将关键字参数拆分为函数并作为表返回。然后我使用LIKE约束在该表上执行左连接。

所以,我的工作非常漂亮,然后突然停止工作。现在它返回每一行,而不仅仅是它所需的行。

另一个警告是,如果关键字参数为空,则应忽略它。

鉴于以下内容,是否有A)明显的错误,或者B)更有效的方法来解决这个问题?

以下是我目前的情况:

ALTER PROCEDURE [dbo].[usp_getOppsPaged] 
@startRowIndex int,
@maximumRows int,
@city varchar(100) = NULL,
@state char(2) = NULL,
@zip varchar(10) = NULL,
@classification varchar(15) = NULL,
@startDateMin date = NULL,
@startDateMax date = NULL,
@endDateMin date = NULL,
@endDateMax date = NULL,
@keywords varchar(400) = NULL
AS
BEGIN
SET NOCOUNT ON;

;WITH Results_CTE AS
(
    SELECT opportunities.*,
    organizations.*,
    departments.dept_name,
    departments.dept_address,
    departments.dept_building_name,
    departments.dept_suite_num,
    departments.dept_city,
    departments.dept_state,
    departments.dept_zip,
    departments.dept_international_address,
    departments.dept_phone,
    departments.dept_website,
    departments.dept_gen_list,
    ROW_NUMBER() OVER (ORDER BY opp_id) AS RowNum
    FROM opportunities 
    JOIN departments ON opportunities.dept_id = departments.dept_id 
    JOIN organizations ON departments.org_id=organizations.org_id
    LEFT JOIN Split(',',@keywords) AS kw ON 
        (title LIKE '%'+kw.s+'%' OR
        [description] LIKE '%'+kw.s+'%' OR
        tasks LIKE '%'+kw.s+'%' OR
        requirements LIKE '%'+kw.s+'%' OR
        comments LIKE '%'+kw.s+'%')
    WHERE 
    (
        (@city IS NOT NULL AND (city LIKE '%'+@city+'%' OR dept_city LIKE '%'+@city+'%' OR org_city LIKE '%'+@city+'%'))
        OR
        (@state IS NOT NULL AND ([state] = @state OR dept_state = @state OR org_state = @state))
        OR
        (@zip IS NOT NULL AND (zip = @zip OR dept_zip = @zip OR org_zip = @zip))
        OR
        (@classification IS NOT NULL AND (classification LIKE '%'+@classification+'%'))
        OR
        ((@startDateMin IS NOT NULL AND @startDateMax IS NOT NULL) AND ([start_date] BETWEEN @startDateMin AND @startDateMax))
        OR
        ((@endDateMin IS NOT NULL AND @endDateMax IS NOT NULL) AND ([end_date] BETWEEN @endDateMin AND @endDateMax))

        OR
        (
            (@city IS NULL AND 
            @state IS NULL AND 
            @zip IS NULL AND 
            @classification IS NULL AND 
            @startDateMin IS NULL AND 
            @startDateMax IS NULL AND 
            @endDateMin IS NULL AND 
            @endDateMin IS NULL)
        )
    )
)

SELECT *
FROM Results_CTE
WHERE RowNum >= @startRowIndex
AND RowNum < @startRowIndex + @maximumRows;
END

1 个答案:

答案 0 :(得分:0)

查询 -

  1. 您能告诉我们以前的版本吗?
  2. 您是否使用任何源代码管理来跟踪所做的更改?
  3. 我的建议

    Predicate一样%%似乎非常昂贵且进程缓慢。您是否可以使用Full Text Index

    为每个local variable声明Input Parameter。将相应的列名称分配给此变量。对于City,由于正在使用三列,因此为City声明三个变量并分配相应的列名称,如下所示......

    Set @Local_city = 'city'
    Set @Local_dept_city = 'dept_city'
    

    最后你可以在Where clause中使用它。这样做将排除下面的代码行。

    OR
     (
           (@city IS NULL AND 
           @state IS NULL AND 
           @zip IS NULL AND 
           @classification IS NULL AND 
           @startDateMin IS NULL AND 
           @startDateMax IS NULL AND 
           @endDateMin IS NULL AND 
           @endDateMin IS NULL)
    

      

    所以,我的工作非常漂亮,然后突然之间   停止工作。现在它返回每一行,而不仅仅是行   它需要。

    您确定查询中使用的运算符吗?我的意思是你到处都有OR运营商。

      

    另一个警告是,如果关键字参数为空,则应该   忽略它。

    请检查我的上述建议。

    最终查询

    ALTER PROCEDURE [dbo].[usp_getOppsPaged] 
    @startRowIndex int,
    @maximumRows int,
    @city varchar(100) = NULL,
    @state char(2) = NULL,
    @zip varchar(10) = NULL,
    @classification varchar(15) = NULL,
    @startDateMin date = NULL,
    @startDateMax date = NULL,
    @endDateMin date = NULL,
    @endDateMax date = NULL,
    @keywords varchar(400) = NULL
    AS
    BEGIN
    SET NOCOUNT ON;
    
    Declare @Local_city varchar(100)
    declare @Local_dept_city varchar(100)
    declare @Local_org_city varchar(100)
    Declare @Local_state char(2)
    Declare @Local_dept_state char(2)
    Declare @Local_org_state char(2)
    Declare @Local_zip varchar(10)
    Declare @Local_dept_zip varchar(10)
    Declare @Local_org_zip varchar(10)
    Declare @Local_classification varchar(15)
    Declare @Local_startDateMin date
    Declare @Local_startDateMax date
    Declare @Local_endDateMin date
    Declare @Local_endDateMin date
    Declare @Local_endDateMax date
    
    Set @Local_city = 'city'
    Set @Local_dept_city = 'dept_city'
    Set @Local_org_city = 'org_city'
    Set @Local_state = 'state'
    Set @Local_dept_state = 'dept_state'
    Set @Local_org_state = 'org_state'
    Set @Local_zip = 'zip'
    Set @Local_dept_zip = 'dept_zip'
    Set @Local_org_zip = 'org_zip'
    Set @Local_classification = 'classification'
    Set @Local_startDateMax = 'startDateMax'
    Set @Local_endDateMin = 'endDateMin'
    Set @Local_endDateMin = 'endDateMin'
    Set @Local_endDateMax = 'endDateMax'
    
    ;WITH Results_CTE AS
    (
        SELECT opportunities.*,
        organizations.*,
        departments.dept_name,
        departments.dept_address,
        departments.dept_building_name,
        departments.dept_suite_num,
        departments.dept_city,
        departments.dept_state,
        departments.dept_zip,
        departments.dept_international_address,
        departments.dept_phone,
        departments.dept_website,
        departments.dept_gen_list,
        ROW_NUMBER() OVER (ORDER BY opp_id) AS RowNum
        FROM opportunities 
        JOIN departments ON opportunities.dept_id = departments.dept_id 
        JOIN organizations ON departments.org_id=organizations.org_id
        LEFT JOIN Split(',',@keywords) AS kw ON 
            (title LIKE '%'+kw.s+'%' OR
            [description] LIKE '%'+kw.s+'%' OR
            tasks LIKE '%'+kw.s+'%' OR
            requirements LIKE '%'+kw.s+'%' OR
            comments LIKE '%'+kw.s+'%')
        WHERE 
        (
            (@city IS NOT NULL AND (city LIKE '%'+@Local_city+'%' OR dept_city LIKE '%'+@Local_dept_city+'%' OR org_city LIKE '%'+@Local_org_city+'%'))
            OR
            (@state IS NOT NULL AND ([state] = @Local_state OR dept_state = @Local_dept_state OR org_state = @Local_org_state))
            OR
            (@zip IS NOT NULL AND (zip = @Local_zip OR dept_zip = @Local_dept_zip OR org_zip = @Local_org_zip))
            OR
            (@classification IS NOT NULL AND (classification LIKE '%'+@Local_classification+'%'))
            OR
            ((@startDateMin IS NOT NULL AND @Local_startDateMax IS NOT NULL) AND ([start_date] BETWEEN @Local_startDateMax AND @Local_startDateMax))
            OR
            ((@endDateMin IS NOT NULL AND @Local_endDateMax IS NOT NULL) AND ([end_date] BETWEEN @Local_endDateMin AND @Local_endDateMax))
        )
    )
    
    SELECT *
    FROM Results_CTE
    WHERE RowNum >= @startRowIndex
    AND RowNum < @startRowIndex + @maximumRows;
    END