2016-04-03 53 views
0

我正在嘗試創建一個用於過濾訂單的存儲過程。基本上用戶可以選擇按日期和日期過濾訂單。所以他們可以通過日期搜索,日期或使用兩者,如果它是有道理的?存儲過程日期從和日期到

反正這是我的SQL Server存儲過程到目前爲止

ALTER PROCEDURE [dbo].[CN_GetOrderItemByCustID] 
    @CustomerID int, 
    @OrderItemWRClass varchar(max) = NULL, 
    @OrderItemSKUName varchar(50) = NULL, 
    @OrderItemDateFrom Datetime, 
    @OrderItemDateTo Datetime 
AS 
BEGIN 
    SET NOCOUNT ON; 

    IF DATEDIFF(d, @OrderItemDateFrom, '01/01/1970') = 0 
     SET @OrderItemDateFrom = null 
    IF DATEDIFF(d, @OrderItemDateTo, '01/01/1970') = 0 
     SET @OrderItemDateTo = null 

    -- Insert statements for procedure here 
    SELECT 
     COM_OrderItem.OrderItemID, COM_Order.OrderID, 
     COM_Order.OrderDate, COM_OrderItem.OrderItemUnitCount, 
     COM_OrderItem.OrderItemStatus, COM_OrderItem.OrderItemSKUNAME, 
     COM_OrderItem.OrderItemSKUID 
    FROM 
     COM_OrderItem 
    INNER JOIN 
     COM_Order ON COM_Order.OrderID = COM_OrderItem.OrderItemOrderID 
    WHERE 
     COM_Order.OrderCustomerID = @CustomerID 
     OR COM_OrderItem.OrderItemWRClass LIKE @OrderItemWRClass + '%' 
     OR COM_OrderItem.OrderItemSKUName LIKE @OrderItemSKUName + '%' 
     OR CONVERT(VARCHAR, COM_Order.OrderDate, 120) LIKE @OrderItemDateFrom + '%' 
    ORDER BY 
     COM_Order.OrderDate DESC 

但是我不知道如何把從(OrderItemDateFrom)的日期和日期(OrderItemDateTo)在最後的SQL語句?

我應該使用OR CONVERT(VARCHAR, COM_Order.OrderDate, 120) LIKE @OrderItemDateFrom + '%' - 這給了我一個錯誤從字符串轉換日期和/或時間時

轉換失敗。

我知道在一個正常的SQL查詢,我會用Between OrderItemDateFrom and OrderItemDateTo

感謝

+0

@Thierry我不知道該鏈接是如何幫助我嗎? – Kevin

+0

道歉,錯誤的線程。將在一秒鐘內刪除它。 – Thierry

+0

@Kevin使用'BETWEEN'進行更清晰的查詢 – Sherlock

回答

0

使用此邏輯

ALTER PROCEDURE [dbo].[CN_GetOrderItemByCustID] 
-- Add the parameters for the stored procedure here 
@CustomerID int, 
@OrderItemWRClass varchar(max) = NULL, 
@OrderItemSKUName varchar(50) = NULL, 
@OrderItemDateFrom Datetime, 
@OrderItemDateTo Datetime 
AS 
BEGIN 

SET NOCOUNT ON; 

IF DATEDIFF(d,@OrderItemDateFrom,'01/01/1970')=0 SET @OrderItemDateFrom = '01/01/1970'; 
IF DATEDIFF(d,@OrderItemDateTo,'01/01/1970')=0 SET @OrderItemDateTo = '31/12/2199'; 

-- Insert statements for procedure here 
SELECT COM_OrderItem.OrderItemID, COM_Order.OrderID, COM_Order.OrderDate, COM_OrderItem.OrderItemUnitCount, COM_OrderItem.OrderItemStatus, COM_OrderItem.OrderItemSKUNAME, 
COM_OrderItem.OrderItemSKUID 
FROM COM_OrderItem 
INNER JOIN COM_Order ON COM_Order.OrderID = COM_OrderItem.OrderItemOrderID 
WHERE COM_Order.OrderCustomerID = @CustomerID OR COM_OrderItem.OrderItemWRClass LIKE @OrderItemWRClass + '%' OR COM_OrderItem.OrderItemSKUName LIKE @OrderItemSKUName + '%' 
OR (COM_OrderDate>[email protected] && COM_OrderDate<[email protected]) 
ORDER BY COM_Order.OrderDate DESC 

試試吧。它應該工作。

+0

感謝您的建議。然而,還有一件事我應該將COM_OrderDate字段轉換或轉換爲varchar?由於這些值隨着時間被存儲,例如, '2016-03-08 10:40:12.477'因爲我只通過日期。謝謝 – Kevin

+0

@Kevin不要緊,直接使用'2016-03-08' – mvikhona

+0

@Kevin你試過了嗎?請提及您是否遇到任何錯誤。 – mvikhona

0

通過允許@OrderItemDateFrom@OrderItemDateTo的NULL值可以簡化您的邏輯。另外,如果過濾器值和列值都DATETIME S,你應該嘗試直接比較,允許索引慣例(如果在DATETIME列中的任何應用):

ALTER PROCEDURE [dbo].[CN_GetOrderItemByCustID] 
    @CustomerID int, 
    @OrderItemWRClass varchar(max) = NULL, 
    @OrderItemSKUName varchar(50) = NULL, 
    @OrderItemDateFrom Datetime = NULL, -- TODO: change caller to not provide parameter, or leave it to null 
    @OrderItemDateTo Datetime = NULL -- TODO: change caller to not provide parameter, or leave it to null 
AS 
BEGIN 
    SET NOCOUNT ON; 

    -- when working with dates try to use an unambiguous format like 'YYYY-MM-DD' 
    SET @OrderItemDateFrom = ISNULL(@OrderItemDateFrom, '1970-01-01') 
    -- assign a very large date to act like not provided 
    -- going one day after to catch DATETIMEs with provided time 
    SET @OrderItemDateTo = DATEADD(day, 1, ISNULL(@OrderItemDateTo, '3000-01-01')) 

    -- Insert statements for procedure here 
    SELECT 
     COM_OrderItem.OrderItemID, COM_Order.OrderID, 
     COM_Order.OrderDate, COM_OrderItem.OrderItemUnitCount, 
     COM_OrderItem.OrderItemStatus, COM_OrderItem.OrderItemSKUNAME, 
     COM_OrderItem.OrderItemSKUID 
    FROM COM_OrderItem 
    INNER JOIN COM_Order ON COM_Order.OrderID = COM_OrderItem.OrderItemOrderID 
    WHERE COM_Order.OrderCustomerID = @CustomerID 
     OR COM_OrderItem.OrderItemWRClass LIKE @OrderItemWRClass + '%' 
     OR COM_OrderItem.OrderItemSKUName LIKE @OrderItemSKUName + '%' 
     -- between can be used 
     OR (COM_OrderDate BETWEEN @OrderItemDateFrom AND @OrderItemDateTo) 
    ORDER BY 
     COM_Order.OrderDate DESC 
END 

另一種選擇是使用動態SQL和構建它基於參數值(即如果提供了過濾器值,則插入WHERE條件)。當過濾器數量相對於過濾器的總數量相對較低時,這一點特別有用,因爲OR s對性能不友好。

注意:不應該結合使用您的過濾器(即使用AND而不是OR)?允許用戶在同一時間過濾多個值是有意義的。

0
ALTER PROCEDURE [dbo].[CN_GetOrderItemByCustID] 
@CustomerID int, 
@OrderItemWRClass varchar(max) = NULL, 
@OrderItemSKUName varchar(50) = NULL, 
@OrderItemDateFrom Datetime, 
@OrderItemDateTo Datetime 
AS 
BEGIN 
SET NOCOUNT ON; 

IF DATEDIFF(d, @OrderItemDateFrom, '01/01/1970') = 0 
    SET @OrderItemDateFrom = null 
IF DATEDIFF(d, @OrderItemDateTo, '01/01/1970') = 0 
    SET @OrderItemDateTo = null 

-- Insert statements for procedure here 
SELECT 
    COM_OrderItem.OrderItemID, COM_Order.OrderID, 
    COM_Order.OrderDate, COM_OrderItem.OrderItemUnitCount, 
    COM_OrderItem.OrderItemStatus, COM_OrderItem.OrderItemSKUNAME, 
    COM_OrderItem.OrderItemSKUID 
FROM 
    COM_OrderItem 
INNER JOIN 
    COM_Order ON COM_Order.OrderID = COM_OrderItem.OrderItemOrderID 
WHERE 
    COM_Order.OrderCustomerID = @CustomerID 
    OR COM_OrderItem.OrderItemWRClass LIKE @OrderItemWRClass + '%' 
    OR COM_OrderItem.OrderItemSKUName LIKE @OrderItemSKUName + '%' 
    OR (@OrderItemDateFrom IS NULL OR COM_Order.OrderDate >[email protected]) 
    OR (@OrderItemDateTo IS NULL OR COM_Order.OrderDate <[email protected]) 
ORDER BY 
    COM_Order.OrderDate DESC 

你應該試試這個。

OR (@OrderItemDateFrom IS NULL OR COM_Order.OrderDate >[email protected]) 
OR (@OrderItemDateTo IS NULL OR COM_Order.OrderDate <[email protected]) 

只需編輯並嘗試這個條件..