SQL Server中具有条件的子句

时间:2015-10-20 19:08:11

标签: sql-server stored-procedures

我在网站上有一个搜索页面的SQL存储过程,用户可以在两个日期字段之间和之间搜索记录:initiatedDateStart和initiatedDateEnd。 SQL查询的逻辑应如下所示:

  • 如果startDate有值,但endDate为空或等于 startDate,返回在startDate上创建的记录。
  • 如果startDate有值,则endDate值大于
    startDate,返回两次创建BETWEEN的记录 日期。

由于我不是SQL专家,我的存储过程不是很优雅或聪明,但它会返回我期望的记录,但日期字段除外。我已经研究过这个,但语法和逻辑让我感到难过。这是我的存储过程的片段。如果在initStartDate texbox中输入了值,但initEndDate为空,则返回在开始日期之后创建的所有记录。我很感激这方面的任何帮助。

DECLARE @initStartDate datetime = NULL
DECLARE @initEndDate datetime = NULL

SELECT DISTINCT 
        d.[DCRId],      
        d.[Title], 
        d.[FiscalYear] 
        FROM [dbo].[tblDCR] d 
        LEFT OUTER JOIN [dbo].[tblWorkflow] orig ON (d.[DCRId] = orig.[DCRId] AND orig.StepName = 'Draft')
        WHERE 1 = 1
        AND (orig.BadgeDate >= @initStartDate OR @initStartDate IS NULL)
        AND (orig.BadgeDate <= @initEndDate OR @initEndDate IS NULL)

3 个答案:

答案 0 :(得分:2)

我能想到的最好的方法是使用动态sql

DECLARE @initStartDate datetime = NULL;
DECLARE @initEndDate   datetime = NULL;
Declare @Sql NVARCHAR(MAX);


SET @Sql  = N'SELECT DISTINCT 
                    d.[DCRId],      
                    d.[Title], 
                    d.[FiscalYear] 
            FROM [dbo].[tblDCR] d 
            LEFT OUTER JOIN [dbo].[tblWorkflow] orig 
            ON (d.[DCRId] = orig.[DCRId] AND orig.StepName = ''Draft'')
            WHERE 1 = 1 '
            + CASE WHEN @initStartDate IS NOT NULL THEN 
                N' AND orig.BadgeDate >= @initStartDate ' ELSE N'' END
            + CASE WHEN @initEndDate IS NOT NULL THEN 
                N' AND orig.BadgeDate <= @initEndDate  ' ELSE N'' END

Exec sp_executesql @Sql
                  ,N'@initStartDate datetime, @initEndDate datetime'
                  ,@initStartDate
                  ,@initEndDate

答案 1 :(得分:0)

但如果@initStartDate没有值怎么办? 如果没有startDate条件,假设您希望它一直返回,那么,将日期条件作为Nullable参数传递,如下所示: 然后,(假设数据库字段只是没有时间的日期),请使用以下where子句:

 where orig.BadgeDate Between
     Coalesce(@initStartDate, orig.BadgeDate) and
     Coalesce(@initEndDate, @initStartDate, orig.BadgeDate)

答案 2 :(得分:0)

我认为您的问题的解决方案是将当前日期分配给结尾参数时保留为NULL。通过这样做,用户可以输入任何参数并获取当前日期值,仅输入开始日期并获取开始日期的数据,或输入结束日期并获取当前日期和结束日期之间的数据。作为最后一个问题,如果由于某种原因用户提出的开始日期高于结束日期,您可以告诉程序仅返回今天的数据。

CREATE PROCEDURE test_proc
@initStartDate date = null,
@initEndDate date = null
AS
IF @initStartDate IS NULL AND @initEndDate IS NULL
BEGIN 
SET @initStartDate = (SELECT GETDATE())
SET @initEndDate = @initStartDate
END
ELSE IF @initStartDate IS NULL AND @initEndDate IS NOT NULL
BEGIN 
SET @initStartDate = @initEndDate 
END
ELSE IF @initEndDate IS NULL AND @initStartDate IS NOT NULL
BEGIN 
SET @initEndDate = @initStartDate
END

IF @initStartDate > @initEndDate
BEGIN
SET @initStartDate = (SELECT GETDATE())
SET @initEndDate = @initStartDate
END  


SELECT DISTINCT 
    d.[DCRId],      
    d.[Title], 
    d.[FiscalYear] 
    FROM [dbo].[tblDCR] d 
    LEFT OUTER JOIN [dbo].[tblWorkflow] orig ON (d.[DCRId] = orig.[DCRId] AND orig.StepName = 'Draft')
    WHERE orig.BadgeDate BETWEEN @initStartDate AND @initEndDate
GO

我修改过的SQL

DECLARE @initStartDate date = '10/21/15'
DECLARE @initEndDate date = NULL

IF @initStartDate IS NULL AND @initEndDate IS NOT NULL
BEGIN
SET @initStartDate = @initEndDate
END
ELSE IF @initEndDate IS NULL AND @initStartDate IS NOT NULL
BEGIN
SET @initEndDate = @initStartDate
END


SELECT DISTINCT 
        d.[DCRId],      
        d.[Title], 
        d.[FiscalYear] 
        FROM [dbo].[tblDCR] d 
        LEFT OUTER JOIN [dbo].[tblWorkflow] orig ON (d.[DCRId] = orig.[DCRId] AND orig.StepName = 'Draft')
        WHERE 1 = 1
        AND (orig.BadgeDate BETWEEN @initStartDate AND @initEndDate) OR (@initStartDate IS NULL OR @initEndDate IS NULL)