使用sql将当前月份显示为日历

时间:2011-03-01 08:50:42

标签: sql sql-server tsql

如何编写t-sql以日历格式显示当前月份?

输出应该像

sun  mon  tues  wed  thur  fri  sat
           1      2     3     4    5
6    7     8      9     10    11   12
13   14    15     ................

应该提供当月的日历

这是我到目前为止所拥有的

declare @start int
declare @day int
declare @space varchar(100)
declare @nodays int
select @start=1
select @space=''
select @nodays=datediff(dd,getdate(),dateadd(mm,1,getdate()))
select @day=case datename(dw,cast(year(getdate()) as varchar(10)) + '-' +cast(month(getdate()) as varchar(10)) + '-' +cast(day(getdate()) as varchar(10))) when 'Sunday' then 1 when 'Monday' then 2 when 'tuesday' then 3 when 'wednesday' then 4 when 'thursday' then 5 when 'friday' then 6 when 'saturday' then 7 end
while(@start<=@nodays)
    if(@day=1)
        if(len(@space)=0)
            select @space=cast(@start as varchar(10))
        else
            select @space=@space+' '+
            case when len(cast(@start as varchar(10)))=1 
            then ' ' 
            else '' 
            end +
            cast(@start as varchar(10))
    else
        if(len(@space)=0)
            select @space=@space+ 
            replicate(char(10),@start) +
            case when len(cast(@start as varchar(10)))=1 
            then ' ' 
            else '' 
            end +
            cast(@start as varchar(10))
        else
            select @space=@space+char(10) + case when len(cast(@start as varchar(10)))=1 then ' ' else '' end +cast(@start as varchar(10))
    select @start=@start+1
print @space+char(10)

6 个答案:

答案 0 :(得分:3)

如果愿意,可以将getdate()更改为本地声明的变量。

;with monthDates
as
(
    select  DATEADD(month, datediff(month, 0, getdate()),0) as d
            ,DATEPART(week, DATEADD(month, datediff(month, 0, getdate()),0)) as w
    union all
    select  DATEADD(day, 1, d)
            ,DATEPART(week, DATEADD(day, 1, d))
    from monthDates
    where d < DATEADD(month, datediff(month, 0, getdate())+1,-1)
)

select  max(case when datepart(dw, d) = 1 then datepart(d,d) else null end) as [Sun]
        ,max(case when datepart(dw, d) = 2 then datepart(d,d) else null end) as [Mon]
        ,max(case when datepart(dw, d) = 3 then datepart(d,d) else null end) as [Tue]
        ,max(case when datepart(dw, d) = 4 then datepart(d,d) else null end) as [Wed]
        ,max(case when datepart(dw, d) = 5 then datepart(d,d) else null end) as [Thu]
        ,max(case when datepart(dw, d) = 6 then datepart(d,d) else null end) as [Fri]
        ,max(case when datepart(dw, d) = 7 then datepart(d,d) else null end) as [Sat]
from monthDates
group by w

答案 1 :(得分:1)

我不知道你到底想要做什么。使用T-SQL打印日历月可能不是您想要做的。

这是一个查询,它为您提供当月内的所有日期作为结果集。如果你只想要一个月的日期编号(就像你一样),你可以使用datepart(d, [Date])来获得它。

;with cteLim as
(
  select
    dateadd(m, datediff(m, 0, getdate()), 0) as FirstDay,
    dateadd(m, datediff(m, 0, getdate())+1, 0)-1 as LastDay
),
cteDays as
(
  select FirstDay as [Date]
  from cteLim
  union all
  select cteDays.[Date] + 1 as [Date]
  from cteDays
    inner join cteLim
      on cteDays.[Date] < cteLim.LastDay
)    
select [Date]
from cteDays

相同的功能,但将结果拆分为“日历”

;with cteLim as
(
  select
    dateadd(m, datediff(m, 0, getdate()), 0) as FirstDay,
    dateadd(m, datediff(m, 0, getdate())+1, 0)-1 as LastDay
),
cteDays as
(
  select FirstDay as [Date]
  from cteLim
  union all
  select cteDays.[Date] + 1 as [Date]
  from cteDays
    inner join cteLim
      on cteDays.[Date] < cteLim.LastDay
)    
select
  datepart(iso_week, [Date]) as [Week],
  (select datepart(d, D2.[Date])
   from cteDays as D2
   where
    datepart(iso_week, D2.[Date]) = datepart(iso_week, D1.[Date]) and
    datepart(dw, D2.[Date]) = 2) as Mon,
  (select datepart(d, D2.[Date])
   from cteDays as D2
   where
    datepart(iso_week, D2.[Date]) = datepart(iso_week, D1.[Date]) and
    datepart(dw, D2.[Date]) = 3) as Tue,
  (select datepart(d, D2.[Date])
   from cteDays as D2
   where
    datepart(iso_week, D2.[Date]) = datepart(iso_week, D1.[Date]) and
    datepart(dw, D2.[Date]) = 4) as Wed,
  (select datepart(d, D2.[Date])
   from cteDays as D2
   where
    datepart(iso_week, D2.[Date]) = datepart(iso_week, D1.[Date]) and
    datepart(dw, D2.[Date]) = 5) as Thu,
  (select datepart(d, D2.[Date])
   from cteDays as D2
   where
    datepart(iso_week, D2.[Date]) = datepart(iso_week, D1.[Date]) and
    datepart(dw, D2.[Date]) = 6) as Fri,
  (select datepart(d, D2.[Date])
   from cteDays as D2
   where
    datepart(iso_week, D2.[Date]) = datepart(iso_week, D1.[Date]) and
    datepart(dw, D2.[Date]) = 7) as Sat,
  (select datepart(d, D2.[Date])
   from cteDays as D2
   where
    datepart(iso_week, D2.[Date]) = datepart(iso_week, D1.[Date]) and
    datepart(dw, D2.[Date]) = 1) as Sun
from cteDays as D1
group by datepart(iso_week, [Date])

结果

Week        Mon         Tue         Wed         Thu         Fri         Sat         Sun
----------- ----------- ----------- ----------- ----------- ----------- ----------- -----------
9           NULL        1           2           3           4           5           6
10          7           8           9           10          11          12          13
11          14          15          16          17          18          19          20
12          21          22          23          24          25          26          27
13          28          29          30          31          NULL        NULL        NULL

答案 2 :(得分:1)

忘记你的'程序代码来制作动态日历'方法:SQL是一种声明性语言,所以请考虑基于集合的解决方案。

创建一个永久Calendar表,其中包含您可能需要的所有过去和未来日期(应该只有几万行),然后在需要时使用CURRENT_TIMESTAMP查询此表。

请参阅Why should I consider using an auxiliary calendar table?

答案 3 :(得分:1)

select DATEPART(MONTH,getdate()) - 获取月号

select Datename(month,getdate()) - 获取月份名称

答案 4 :(得分:0)

这里有一个链接:Creating a Calendar in a single SQL statement

SELECT LPAD(MONTH, 20 - (20 - LENGTH(MONTH)) / 2) MONTH, "Sun", "Mon", "Tue", "Wed",     "Thu", "Fri", "Sat"
  FROM (SELECT TO_CHAR(dt, 'fmMonthfm YYYY') MONTH,
               TO_CHAR(dt + 1, 'iw') week,
               MAX(DECODE(TO_CHAR(dt, 'd'), '1', LPAD(TO_CHAR(dt, 'fmdd'), 2))) "Sun",
               MAX(DECODE(TO_CHAR(dt, 'd'), '2', LPAD(TO_CHAR(dt, 'fmdd'), 2))) "Mon",
               MAX(DECODE(TO_CHAR(dt, 'd'), '3', LPAD(TO_CHAR(dt, 'fmdd'), 2))) "Tue",
               MAX(DECODE(TO_CHAR(dt, 'd'), '4', LPAD(TO_CHAR(dt, 'fmdd'), 2))) "Wed",
               MAX(DECODE(TO_CHAR(dt, 'd'), '5', LPAD(TO_CHAR(dt, 'fmdd'), 2))) "Thu",
               MAX(DECODE(TO_CHAR(dt, 'd'), '6', LPAD(TO_CHAR(dt, 'fmdd'), 2))) "Fri",
               MAX(DECODE(TO_CHAR(dt, 'd'), '7', LPAD(TO_CHAR(dt, 'fmdd'), 2))) "Sat"
          FROM (SELECT TRUNC(SYSDATE, 'y') - 1 + ROWNUM dt
                  FROM all_objects
                  WHERE ROWNUM <= ADD_MONTHS(TRUNC(SYSDATE, 'y'), 12) -
                       TRUNC(SYSDATE, 'y'))
         GROUP BY TO_CHAR(dt, 'fmMonthfm YYYY'), TO_CHAR(dt + 1, 'iw'))
 ORDER BY TO_DATE(MONTH, 'Month YYYY'), TO_NUMBER(week);

您可以添加一些子句来指定月份

答案 5 :(得分:0)

DECLARE @Year int, @Month int, @LastDay int;
SET @Year = 2011;
SET @Month = 2;
SET @LastDay = DAY(DATEADD(m, 1, CAST(@Year AS varchar) + '-' +
                                 CAST(@Month AS varchar) + '-01') - 1);

WITH dates AS (
  SELECT *, DOW = DATEPART(WEEKDAY, Date), WN = DATEPART(WEEK, Date)
  FROM (
    SELECT
      Date = CAST(CAST(@Year AS varchar) + '-' +
                  CAST(@Month AS varchar) + '-' +
                  CAST(number AS varchar) AS datetime)
    FROM master..spt_values
    WHERE type = 'P'
      AND number BETWEEN 1 AND @LastDay
  ) s
)
SELECT
  Sun = MAX(CASE days.DOW WHEN 1 THEN dates.Date END),
  Mon = MAX(CASE days.DOW WHEN 2 THEN dates.Date END),
  Tue = MAX(CASE days.DOW WHEN 3 THEN dates.Date END),
  Wed = MAX(CASE days.DOW WHEN 4 THEN dates.Date END),
  Thu = MAX(CASE days.DOW WHEN 5 THEN dates.Date END),
  Fri = MAX(CASE days.DOW WHEN 6 THEN dates.Date END),
  Sat = MAX(CASE days.DOW WHEN 7 THEN dates.Date END)
FROM (SELECT DISTINCT DOW FROM dates) days
  CROSS JOIN (SELECT DISTINCT WN FROM dates) weeks
  LEFT JOIN dates ON weeks.WN = dates.WN AND days.DOW = dates.DOW
GROUP BY weeks.WN