SQL查询月/年

时间:2016-04-22 13:38:12

标签: sql sql-server sql-server-2008-r2

我有一个查询,可以从表格“mesure”计算每年/月的值,就像这样

select Annee, Mois
from 
  (
    select  annee, Mois
        --  computing her...
      round(cast(SUM(nbDates) * 100 as float) / sum(NbDatesTheoriques),2) as    DispoBrute ie....
    from (
            select          
            DATEPART(YEAR, DateHeureMesure) as annee, 
            DATEPART(month, dateheuremesure) as Mois
            --TypeMesure,HauteurMesure, count(dateheuremesure) as nbDates,
            --SUM(CASE WHEN ValideeMesure = 2 THEN 1 ELSE 0 END) AS NbDatesValides
            from mesure                     
            where Id = 378                  
            group by DATEPART(YEAR, DateHeureMesure), DATEPART(month, dateheuremesure) 

        ) req
    )   req2
group by annee, mois--, mo.MonthNumber
order by annee, mois --min(datedebut)

我简化了查询(删除子查询req2 / req ...的一部分),结果是:

Year   Month   DispoBrute 
2013    8         156
2013    9         1254
2013    10        121
2013    11        2121
2013    12        4500
2014    1         155 
2014    2         200
2014    3 
2014    4
2014    5

好的,但我怎么能像这样在今年的所有月份?

Year   Month     DispoBrute
2013    1         NULL
2013    2         NULL
2013    3         NULL
2013    4         NULL
2013    5         NULL
2013    6         NULL
2013    7         NULL
2013    8         156
2013    9         1254
2013    10        121
2013    11 ... ...2121
2013    12 ....    ie
2014    1
2014    2
2014    3
2014    4
2014    5

非常感谢!

2 个答案:

答案 0 :(得分:0)

我完全不了解你的目标。但是你可以尝试使用下一个方法

declare @start_date datetime = (select min(DateHeureMesure) from measure)
declare @due_date datetime = (select max(DateHeureMesure) from measure)

declare @months as table (
    the_year int
,   the_month int
)

declare @the_date datetime = @start_date

while @the_date<=@due_date
begin
    insert into @months values(datepart(yy, @the_date), datepart(mm, @the_date))
    set @the_date = dateadd(mm,1,@the_date)
end


select 
    m.*
,   data.grouping_field1
,   data.grouping_field2
,   data.agg_value1
,   data.agg_value2
from @months m
left join (
    select
        datepart(yy, m.DateHeureMesure) the_year
    ,   datepart(mm, m.DateHeureMesure) the_month
    ,   m.grouping_field1
    ,   m.grouping_field2
    ...
    ,   sum(m.agregated_field1) agg_value1
    ,   count(m.agregated_field2) agg_value2
    ...
    from measure m
    group by datepart(yy, m.DateHeureMesure)
    ,        datepart(mm, m.DateHeureMesure)
    ,        m.grouping_field1
    ,        m.grouping_field2
) data on data.the_year = m.the_year
    and   data.the_month = m.the_month
order by m.the_year, m.the_month
  • 表示更好的性能表@months可以是带索引的物理表。但是不要忘记支持自动扩展它。
  • 您可以使用“create function returns table”语法在服务器上为@month表创建生成器函数。然后你就可以像(函数名fn_GenMonths)那样编写单语句SQL:


  select 
      m.*
  ,   data.grouping_field1
  ,   data.grouping_field2
  ,   data.agg_value1
  ,   data.agg_value2
  from fn_GenMonths(@start_date,@due_date) m
  left join (
        select
            datepart(yy, m.DateHeureMesure) the_year
        ,   datepart(mm, m.DateHeureMesure) the_month
        ,   m.grouping_field1
        ,   m.grouping_field2
        ...
        ,   sum(m.agregated_field1) agg_value1
        ,   count(m.agregated_field2) agg_value2
        ...
        from measure m
        group by datepart(yy, m.DateHeureMesure)
        ,        datepart(mm, m.DateHeureMesure)
        ,        m.grouping_field1
        ,        m.grouping_field2
  ) data on   data.the_year = m.the_year
        and   data.the_month = m.the_month
  order by m.the_year, m.the_month

答案 1 :(得分:0)

&#34;它的作品&#34;但是非常缓慢:用年和月来加入临时表:

select the_year, the_month--,NbDatesAvecDonnees,NbDatesTheoriques,NbDatesValides, DispoBrute, DispoValide,dispoBruteCorrigee,dispoValideCorrigee    
from @months
left join 
(
    select Annee, Mois,
    min(datedebut) as dtDebutPeriode, 
    SUM(nbDates) as NbDatesAvecDonnees,
    sum(NbDatesTheoriques) as NbDatesTheoriques,sum(NbDatesValides) as NbDatesValides,
    round(cast(SUM(nbDates) * 100 as float) / sum(NbDatesTheoriques),2) as DispoBrute,
    round(cast(SUM(NbDatesValides) * 100 as float) / sum(NbDatesTheoriques),2) as DispoValide,
    case when sum(nbDatesMinMax) != sum(NbDatesTheoriques) then round(cast(SUM(nbDates) * 100 as float) / sum(nbDatesMinMax),2) else round(cast(SUM(nbDates) * 100 as float) / sum(NbDatesTheoriques),2) end as dispoBruteCorrigee,
    case when sum(nbDatesMinMax) != sum(NbDatesTheoriques) then round(cast(SUM(NbDatesValides) * 100 as float) / sum(nbDatesMinMax),2) else round(cast(SUM(NbDatesValides) * 100 as float) / sum(NbDatesTheoriques),2) end as dispoValideCorrigee
    ,case when sum(nbDatesMinMax) != sum(NbDatesTheoriques) then 1 else 0 end as erreur
  from ( 
    select 
        dateMin, dateMax, (DATEDIFF(minute, dateMin, dateMax) + 10)/10 as nbDatesMinMax, 
        dateDebut, dateadd(second, -1 ,DATEADD(month, 1, datedebut)) as datefin, annee, Mois, 
        (DATEDIFF(minute, datedebut, dateadd(second, -1 ,DATEADD(month, 1, datedebut))) +10 )/10 as NbDatesTheoriques  , nbDates, NbDatesValides  
        from (
                select 
                    min(dateheuremesure) as dateMin, 
                    max(dateheuremesure) as dateMax,
                    DATEADD(day,-(datepart(day,(DATEADD(hour,-(datepart(hour,dateadd(minute,-(datepart(minute, min(dateHeureMesure))), min(dateheuremesure)))), dateadd(minute,-(datepart(minute, min(dateHeureMesure))), min(dateheuremesure)))))) + 1,
                    DATEADD(hour,-(datepart(hour,dateadd(minute,-(datepart(minute, min(dateHeureMesure))), min(dateheuremesure)))), dateadd(minute,-(datepart(minute, min(dateHeureMesure))), min(dateheuremesure))))
                    as dateDebut,
                    DATEPART(year, DateHeureMesure) as annee, 
                    DATEPART(month, dateheuremesure) as mois, TypeMesure, HauteurMesure, 
                    count(dateheuremesure) as nbDates,
                    SUM(CASE WHEN ValideeMesure = 2 THEN 1 ELSE 0 END) AS NbDatesValides
                from mesure                                 
                where IdCampagneMesure = @IdCampagne and DateHeureMesure between @start_date and @due_date              
                group by DATEPART(YEAR, DateHeureMesure), DATEPART(month, dateheuremesure), TypeMesure , HauteurMesure              
            ) r group by annee, dateMin,dateMax,dateDebut,mois,nbDates,NbDatesValides) r2 group by annee,mois
            )                               
    data on data.annee = the_year and data.mois = the_month

enter image description here