【问题标题】:How to get all Mondays or Tuesdays of Previous Month如何获取上个月的所有星期一或星期二
【发布时间】:2016-07-28 23:28:10
【问题描述】:

如何获取上个月的所有星期一或星期二?我还没有看到任何关于它的例子。

【问题讨论】:

  • 一些例子(带 cte)http://bradsruminations.blogspot.ru/search?updated-max=2011-10-04T12:57:00-07:00&max-results=1Step-By-Step Claritytopic
  • 您的问题假定参考日期。因为现在世界上不同的地方有不同的日期,所以“上个月”对不同的人来说可能是不同的。 GETDATE() 使用服务器的时区。这与今天有关吗?如果明天发生变化怎么办?

标签: sql sql-server sql-server-2008 tsql


【解决方案1】:

你可以使用:

DECLARE @d DATE = GETDATE();

SELECT sub.prev_date
FROM (SELECT @d, MONTH(DATEADD(MM, -1, @d))) AS s(d,m)
CROSS APPLY (
    SELECT DATEADD(D, c-1, DATEADD(MM, -1, DATEADD(DD, 1 - DAY(d),d))) AS prev_date
    FROM (
    VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),
           (11),(12),(13),(14),(15),(16),(17),(18),(19),(20),
           (21),(22),(23),(24),(25),(26),(27),(28),(29),(30),(31))AS x(c)
    ) AS sub
WHERE MONTH(sub.prev_date) = s.m 
  AND DATENAME(dw,sub.prev_date) IN ('Monday','Tuesday');

LiveDemo

输出:

╔════════════╗
║ prev_date  ║
╠════════════╣
║ 2016-03-01 ║
║ 2016-03-07 ║
║ 2016-03-08 ║
║ 2016-03-14 ║
║ 2016-03-15 ║
║ 2016-03-21 ║
║ 2016-03-22 ║
║ 2016-03-28 ║
║ 2016-03-29 ║
╚════════════╝

警告:

SQL Server 语言应该是 English 否则 DATENAME 将不匹配。

您也可以与DATEPART weekday 进行比较,但您需要了解SET DATEFIRST 的设置。


编辑:

短一点:

DECLARE @d DATE = '2015-01-01';

SELECT sub.prev_date
FROM (SELECT DATEADD(DD, c - DAY(@d),DATEADD(MM, -1, @d)) AS prev_date
      FROM (VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),
                 (11),(12),(13),(14),(15),(16),(17),(18),(19),(20),
                 (21),(22),(23),(24),(25),(26),(27),(28),(29),(30),(31))AS x(c)) AS sub
WHERE MONTH(sub.prev_date) = MONTH(DATEADD(MM, -1, @d))
  AND DATENAME(dw,sub.prev_date) IN ('Monday','Tuesday');

LiveDemo

【讨论】:

  • 让它以这种方式工作非常聪明。非常感谢!
【解决方案2】:
;WITH CTE (X)
 AS
 (
 SELECT DATEADD(MM,DATEDIFF(MM,0,GETDATE())-1,0)
 ),
 CTE2(N) AS
 (
 SELECT 0
 UNION ALL
 SELECT 1+N  FROM CTE2 WHERE N< (SELECT DATEDIFF(DD,DATEADD(MM,DATEDIFF(MM,0,GETDATE())-1,0),DATEADD(MM,1,DATEADD(MM,DATEDIFF(MM,0,GETDATE())-1,0))-1))
 )
 SELECT DATEADD(DD,N,X),DATENAME(DW,DATEADD(DD,N,X)) FROM CTE,CTE2 WHERE DATENAME(DW,DATEADD(DD,N,X)) IN ('Monday','Tuesday')

【讨论】:

  • 感谢您的解决方案。很整洁。
【解决方案3】:
declare @table table
(
   ID integer identity,
   DateRange date,
   Remark nvarchar(10),
   MonWeek nvarchar(1),
   weekgrp integer
)

declare @from Date
declare @newfrom Date
declare @to Date
declare @min integer
declare @max integer

set @from ='2016-03-01'
set @to = '2016-03-31'
set @newfrom = '2016-03-01'

while @from <= @to
begin
  insert into @table (DateRange, Remark) Values (@from,DATENAME(dw,@from))

  set @from = DATEADD(dd,1,@from)
end

update @table
set MonWeek = 'Y'
where Remark = 'Monday'

select @min = MIN(ID), @max = MAX(ID) from @table
where MonWeek = 'Y'

--to calculate week group
while @min <= @max
begin
   Update @table
   set weekgrp = @min
   where ID between @min and @min + 7
   set @min = @min + 7
end

select * from @table
where Remark in ('Monday','Tuesday')

【讨论】:

    【解决方案4】:
    WITH CTE_DATES 
    AS(
        SELECT CAST(DATEADD(mm, DATEDIFF(mm, 0, GETDATE()) -1, 0) AS DATE) AS [DATE] -- start previous month
    
        UNION ALL
    
        SELECT CAST(DATEADD(DD, 1, [DATE])  AS DATE)
        FROM [CTE_DATES]
        WHERE [DATE] < CAST(DATEADD(ms, -3, DATEADD(mm, DATEDIFF(mm, 0, GETDATE()) + 0, 0)) AS DATE) -- end previous month
    )
    
    SELECT 
         [date] 
        ,DATENAME(WEEKDAY, [date]) AS 'Weekday'
        ,DATEPART(WEEKDAY, [date]) AS 'Day'
    FROM [CTE_DATES]
    WHERE DATEPART(WEEKDAY, [date]) IN (1, 2) 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-05-02
      • 1970-01-01
      • 1970-01-01
      • 2019-08-06
      • 1970-01-01
      • 1970-01-01
      • 2021-09-06
      • 2021-12-04
      相关资源
      最近更新 更多