SQL条件日期过滤器

时间:2014-10-26 12:20:49

标签: sql stored-procedures parameters conditional

我有一个SQL存储过程,我希望根据两个控制参数@FilterOption,@ DateFilterOption的值来应用不同的过滤器。第一个确定字段是否等于,开头或包含并且正常工作。第二个用于确定日期是否等于,大于或小于,并且也可以正常工作。问题是他们不能一起工作。

另外两个参数@FilterValue和@DateFilterValue是用于过滤的实际值。如果我使用所有AND作为日期选项而不是OR,那么它不能正常工作,那么是否有更好的方法来编写HAVING CLAUSE中的日期选项。

由于 CM

create Procedure [dbo].[SelectPagedData]
(
    @FilterValue NVARCHAR(50),
    @CurrentPage INT,
    @PageSize INT,
    @TotalRecords INT OUTPUT,
    @OrderField INT,
    @FilterOption INT,
    @DateFilterOption INT,
    @DateFilterValue DATE
)

As

--FilterOption
--0=none
--1=CustomerStartsWith,
--2=CustomerContains,
--3=CreatedByStartsWith,
--4=CreatedByContains

--@DateFilterOption
--0=none
--1=CreatedByEquals,
--2=CreatedByGreaterThan,
--3=CreatedByLessThan,
--4=ModifiedOnEquals,
--5=ModifiedOnGreaterThan,
--6=ModifiedOnLessThan

-- Turn off count return.
Set NoCount On

-- Declare variables.
Declare @FirstRec int
Declare @LastRec int

-- Initialize variables.
Set @FirstRec = (@CurrentPage - 1) * @PageSize
Set @LastRec = (@CurrentPage * @PageSize + 1)

IF @DateFilterOption = 0 
BEGIN
    SET @DateFilterValue = '1900-01-01' 
END

IF @FilterOption = 0 
BEGIN
    SET @FilterValue = 1 
END

IF @FilterOption = 1 OR @FilterOption = 3
BEGIN
    SET @FilterValue = @FilterValue + '%' 
END

IF @FilterOption = 2 OR @FilterOption = 4
BEGIN
    SET @FilterValue = '%' + @FilterValue + '%' 
END

PRINT @FilterValue

Create Table #TempTable
(
    NewQuoteID INT IDENTITY PRIMARY KEY,
    QuoteID INT,
    GUID UNIQUEIDENTIFIER,
    EquipmentID INT, 
    QuoteName NVARCHAR(50),
    AccountNumber NVARCHAR(50),
    ADName NCHAR(10),
    CreatedOn DATETIME,
    LastModifiedOn DATETIME,
    CustomerName NVARCHAR(100),
    EquipmentName NVARCHAR(200),
    Total DECIMAL(18,2)
)

--Fill the temp table
Insert INTO #TempTable 
(
    QuoteID,
    GUID,
    EquipmentID,
    QuoteName,
    AccountNumber,
    ADName,
    CreatedOn,
    LastModifiedOn,
    CustomerName,
    EquipmentName,
    Total
)
SELECT Q.QuoteID, Q.GUID, Q.EquipmentID, Q.QuoteName, Q.AccountNumber, Q.ADName, Q.CreatedOn, 
  Q.LastModifiedOn, C.CustomerName, E.EquipmentName, SUM(QD.Amount) Total
FROM 
    Quotes Q
JOIN
    Customers C
ON Q.AccountNumber = C.AccountNumber
JOIN
    Equipment E
ON E.EquipmentID = Q.EquipmentID
JOIN
    QuoteDetails QD
ON QD.GUID = Q.GUID
GROUP BY q.QuoteID, Q.GUID, Q.EquipmentID, Q.QuoteName, Q.AccountNumber, Q.ADName,
 Q.LastModifiedOn, Q.CreatedOn,C.CustomerName, E.EquipmentName
HAVING
    (CASE @FilterOption 
    WHEN 0 THEN '1'
    WHEN 1 THEN C.CustomerName 
    WHEN 2 THEN C.CustomerName 
    WHEN 3 THEN Q.ADName 
    WHEN 4 THEN Q.ADName 
    END) LIKE @FilterValue 
 AND
(@DateFilterOption = 0 AND CONVERT(date, Q.CreatedOn,101) > @DateFilterValue)  
OR
(@DateFilterOption = 1 AND CONVERT(date, Q.CreatedOn,101) = @DateFilterValue)  
OR
 (@DateFilterOption = 2 AND CONVERT(date, Q.CreatedOn,101) > @DateFilterValue)  
OR
 (@DateFilterOption = 3 AND CONVERT(date, Q.CreatedOn,101) < @DateFilterValue)  
OR
(@DateFilterOption = 4 AND CONVERT(date, Q.LastModifiedOn,101) = @DateFilterValue)  
OR
(@DateFilterOption = 5 AND CONVERT(date, Q.LastModifiedOn,101) > @DateFilterValue)  
OR
(@DateFilterOption = 6 AND CONVERT(date, Q.LastModifiedOn,101) < @DateFilterValue)  
ORDER BY
    CASE WHEN @OrderField = 0 THEN [QuoteName] END,
    CASE WHEN @OrderField = 1 THEN [QuoteName] END DESC,
    CASE WHEN @OrderField = 2 THEN CreatedOn END,
    CASE WHEN @OrderField = 3 THEN CreatedOn END DESC,
    CASE WHEN @OrderField = 4 THEN LastModifiedOn END,
    CASE WHEN @OrderField = 5 THEN LastModifiedOn END DESC,
    CASE WHEN @OrderField = 6 THEN CustomerName END,
    CASE WHEN @OrderField = 7 THEN CustomerName END DESC,
    CASE WHEN @OrderField = 8 THEN ADName END,
    CASE WHEN @OrderField = 9 THEN ADName END DESC

--Select one page of data based on the record numbers above
Select 
    QuoteID,
    GUID,
    EquipmentID,
    QuoteName,
    AccountNumber,
    ADName,
    CreatedOn,
    LastModifiedOn,
    CustomerName,
    EquipmentName,
    Total
From 
    #TempTable
Where 
    NewQuoteID > @FirstRec 
And 
    NewQuoteID < @LastRec
ORDER BY 
    CASE WHEN @OrderField = 0 THEN [QuoteName] END,
    CASE WHEN @OrderField = 1 THEN [QuoteName] END DESC,
    CASE WHEN @OrderField = 2 THEN CreatedOn END,
    CASE WHEN @OrderField = 3 THEN CreatedOn END DESC,
    CASE WHEN @OrderField = 4 THEN LastModifiedOn END,
    CASE WHEN @OrderField = 5 THEN LastModifiedOn END DESC,
    CASE WHEN @OrderField = 6 THEN CustomerName END,
    CASE WHEN @OrderField = 7 THEN CustomerName END DESC,
    CASE WHEN @OrderField = 8 THEN ADName END,
    CASE WHEN @OrderField = 9 THEN ADName END DESC

SELECT 
    @TotalRecords = COUNT(*)
FROM 
   #TempTable

1 个答案:

答案 0 :(得分:1)

我认为问题只是你的括号。尝试将having子句更改为:

HAVING (CASE @FilterOption 
            WHEN 0 THEN '1'
            WHEN 1 THEN C.CustomerName 
            WHEN 2 THEN C.CustomerName 
            WHEN 3 THEN Q.ADName 
            WHEN 4 THEN Q.ADName 
        END) LIKE @FilterValue AND
       ((@DateFilterOption = 0 AND CONVERT(date, Q.CreatedOn,101) > @DateFilterValue) OR
        (@DateFilterOption = 1 AND CONVERT(date, Q.CreatedOn,101) = @DateFilterValue) OR
        (@DateFilterOption = 2 AND CONVERT(date, Q.CreatedOn,101) > @DateFilterValue) OR
        (@DateFilterOption = 3 AND CONVERT(date, Q.CreatedOn,101) < @DateFilterValue) OR
        (@DateFilterOption = 4 AND CONVERT(date, Q.LastModifiedOn,101) = @DateFilterValue) OR
        (@DateFilterOption = 5 AND CONVERT(date, Q.LastModifiedOn,101) > @DateFilterValue) OR
        (@DateFilterOption = 6 AND CONVERT(date, Q.LastModifiedOn,101) < @DateFilterValue)
       ) 

另外两条评论。首先,在where子句中进行过滤通常更有效,因为它减少了聚合所需的数据量。其次,您不需要转换存储为日期的日期值。并且,将日期存储为字符串是一个坏主意。所以,各种日期应该已经是日期。如果它们是datetime并且您只想将它​​们转换为date,请将第三个参数移至convert()。这用于将字符串转换为日期。 (实际上,在这种情况下我总是使用cast(col as date),但cast()convert()都可以。{/ p>