优化日期之间的选择

时间:2018-08-12 23:38:34

标签: sql-server optimization query-optimization

我的存储过程确实表现很差。有什么改进建议吗?

 select  t2.ID,
    t2.Transactions,
    t2.StartTime,
    t2.EndTime,
    t2.Good,
    t2.OK,
    t2.Bad,
    t1.PID,
    t1.PName
from(
select distinct ID,
     max([PID]) as MaxPID, 
     min([DATE_S]) as StartTime,
     max([DATE_S]) as EndTime,  
     count([ID_P]) as Transactions,
     coalesce(count(case when [STATUS] = 0 then 1 end), 0)  as Good,
     coalesce(count(case when [STATUS] = 1 then 1 end), 0)  as Warning,
     coalesce(count(case when [STATUS] > 1 then 1 end), 0)  as Bad
 from  [dbo].[Table1]
 where CONVERT(date, [DATE_S]) between CONVERT(date, @StartDate) and 
 CONVERT(date, @EndDate)
 group by ID) t2
 LEFT join [dbo].[Table2] t1 on t2.MaxPID = t1.[PID] 
order by ID desc

非常感谢任何提示。

4 个答案:

答案 0 :(得分:0)

一些假设-您的@startdate和@enddate是日期(没有时间成分),您的数据库记录是datetime。还要假设date_s上有一个索引,但是没有使用它,因为您没有在where子句中直接使用它。解决此问题的方法是保留date_s不变,然后在您的between子句中使用@startdate(将在开始日期的午夜使用,@ endDate + 1则将在下一个午夜使用。

当然,如果从第二天的午夜开始,这可能会找到一行,如果是这种情况,则使用第二天1秒或类似的时间。但不太可能成为问题。

where子句:

where DATE_S between @StartDate and dateadd(d,1,@EndDate)

答案 1 :(得分:0)

尝试类似这样的东西:

declare @StartDateDt as datetime=cast(@StartDate as date);
declare @EndDateDt as datetime=cast(EndDate as date);

With tmp as (
select ID, 
     max(PID) as MaxPID, 
     min(DATE_S) as StartTime,
     max(DATE_S) as EndTime,  
     count(ID_P) as Transactions,
     sum(case when STATUS = 0 then 1 else 0 end)  as Good,
     sum(case when STATUS = 1 then 1 else 0 end)  as Warning,
     sum(case when STATUS > 1 then 1 else 0 end)  as Bad
 from  dbo.Table1
 where cast(DATE_S as date) between @StartDateDt  and @EndDateDt
 group by ID
)
select T2.*, T1.PID, T1.PName  
from tmp T1
LEFT join dbo.Table2 T2 on T1.MaxPID = T2.PID
order by T1.ID desc

答案 2 :(得分:0)

select ID,
     max([PID]) as MaxPID, 
     min([DATE_S]) as StartTime,
     max([DATE_S]) as EndTime,  
     count([ID_P]) as Transactions,
     coalesce(count(case when [STATUS] = 0 then 1 end), 0)  as Good,
     coalesce(count(case when [STATUS] = 1 then 1 end), 0)  as Warning,
     coalesce(count(case when [STATUS] > 1 then 1 end), 0)  as Bad int #tmpResult
 from  [dbo].[Table1]
 where CONVERT(date, [DATE_S]) between CONVERT(date, @StartDate) and 
 CONVERT(date, @EndDate)
 group by ID

SELECT  t2.ID,
    t2.Transactions,
    t2.StartTime,
    t2.EndTime,
    t2.Good,
    t2.OK,
    t2.Bad,
    t1.PID,
    t1.PName
FROM #tmpResult t2
 LEFT join [dbo].[Table2] t1 on t2.MaxPID = t1.[PID] 
order by ID desc

答案 3 :(得分:0)

我假设[DATE_S]包含datetime值(日期和时间)

@StartDate@EndDate是日期时间数据类型,但仅包含日期值。

因此在@EndDate中添加1天

set @EndDate=DateADd(day,1,@EndDate)



    select  t2.ID,
        t2.Transactions,
        t2.StartTime,
        t2.EndTime,
        t2.Good,
        t2.OK,
        t2.Bad,
        t1.PID,
        t1.PName
    from(

    select  ID,
         max([PID]) as MaxPID, 
         min([DATE_S]) as StartTime,
         max([DATE_S]) as EndTime,  
         count([ID_P]) as Transactions,
         coalesce(count(case when [STATUS] = 0 then 1 end), 0)  as Good,
         coalesce(count(case when [STATUS] = 1 then 1 end), 0)  as Warning,
         coalesce(count(case when [STATUS] > 1 then 1 end), 0)  as Bad
     from  [dbo].[Table1]
     where [DATE_S]>=@StartDate and [DATE_S]<=@EndDate
     group by ID
    ) t2
     LEFT join [dbo].[Table2] t1 on t2.MaxPID = t1.[PID] 
order by ID desc

Create non Clustered index ix_Date on Table1(DATE_S)include(PID,ID_P,STATUS)

您可以告诉两个表的索引,以便相应地更正我的索引。