Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 查找两个最近的可比较日期(相同的工作日和月份)_Sql Server_Date_Sql Server 2012 - Fatal编程技术网

Sql server 查找两个最近的可比较日期(相同的工作日和月份)

Sql server 查找两个最近的可比较日期(相同的工作日和月份),sql-server,date,sql-server-2012,Sql Server,Date,Sql Server 2012,我试过寻找,但运气不好。我想做的是根据任何输入日期,得到两个最新的日期,它们与输入日期在同一个月的同一天和同一个工作日 例如,2018年7月2日(dd/mm/yyyy)应返回2018年4月2日和2017年10月2日,因为这两个日期都是第二个星期一,也是最近发生的两个 我有一个日期表,我可以与之合作,我正在考虑做一个自己加入得到这个,但我会感谢一些帮助 编辑:忘了提到我正在使用SQL Server 2012如果您有一个日期表,那么您可以使用它。以下伪代码基于ANSI SQL函数,因为日期函数依赖于

我试过寻找,但运气不好。我想做的是根据任何输入日期,得到两个最新的日期,它们与输入日期在同一个月的同一天和同一个工作日

例如,2018年7月2日(dd/mm/yyyy)应返回2018年4月2日和2017年10月2日,因为这两个日期都是第二个星期一,也是最近发生的两个

我有一个日期表,我可以与之合作,我正在考虑做一个自己加入得到这个,但我会感谢一些帮助


编辑:忘了提到我正在使用SQL Server 2012

如果您有一个日期表,那么您可以使用它。以下伪代码基于ANSI SQL函数,因为日期函数依赖于数据库:

select d.*
from dates d
where extract(dow from d.date) = extract(dow from date '2018-07-02') and 
      extract(day from d.date) = extract(day from '2018-07-02') and
      d.date < date '2018-07-02'
order by d.date desc
fetch first 2 rows only;
选择d*
从日期d开始
其中摘录(道琼斯指数自d.date起)=摘录(道琼斯指数自“2018-07-02”日起),以及
摘录(从d.日期算起的日期)=摘录(从'2018-07-02'算起的日期)和
d、 日期<日期'2018-07-02'
按日期说明订购
只取前2行;

您的日期表需要计算每一天的星期几(数字)。然后,只需
JOIN
ing、排序和挑选前两行即可

MS SQL Server 2017架构设置

DECLARE @enteredDate date = '2018-07-02' /* This is the date you entered. */

SELECT TOP 2 s1.testDate
FROM (
  SELECT t1.testDate
    , ROW_NUMBER() OVER ( PARTITION BY t1.testDate ORDER BY t1.testDate DESC, t1.id DESC  ) AS rn
  FROM t1
  INNER JOIN datedim dd ON t1.testDate = dd.theDate
    AND dd.theDay = DATEPART(day,@enteredDate)
    AND dd.theDOW = DATEPART(weekday,@enteredDate)
) s1
WHERE rn = 1 /* Get 1st result for a date. */
ORDER BY s1.testDate DESC
|   testDate |
|------------|
| 2018-04-02 |
| 2017-10-02 |
设置日期表

/********************************CALENDAR********************************/
/* 
    As always, thank you to Aaron Bertrand for the Calendar Table example. 
    https://www.mssqltips.com/sqlservertip/4054/creating-a-date-dimension-or-calendar-table-in-sql-server/
*/

SET DATEFIRST 7 ; /* SUNDAY */ /* Make sure the week starts on the same day. */

CREATE TABLE datedim (
      theDate           date        PRIMARY KEY
    , theDay            AS DATEPART(day, theDate)           --int
    , theWeek           AS DATEPART(week, theDate)          --int 
    , theMonth          AS DATEPART(month, theDate)         --int
    , theYear           AS DATEPART(year, theDate)          --int
    , theDOW            AS DATEPART(weekday, theDate)       --int
    , yyyymmdd          AS CONVERT(char(8), theDate, 112)   /* yyyymmdd */
) ;

/************************************************************************/
/* 
  Use the catalog views to generate as many rows as we need. This example
  creates a date dimension for 1 Sept 2017 to 1 Aug 2018.
*/
INSERT INTO datedim ( theDate ) 
SELECT d
FROM (
    SELECT d = DATEADD(day, s1.rn - 1, '2017-01-01')
    FROM 
    (
        SELECT TOP ( DATEDIFF(day, '2017-01-01', '2018-12-31') )
            rn = ROW_NUMBER() OVER (ORDER BY sao.object_id)
        FROM sys.all_objects sao
    ) s1
) s2
/************************************************************************/
设置测试数据

/* TEST DATA */
CREATE TABLE t1 (id int identity, testDate date) ;

INSERT INTO t1 ( testDate )
VALUES 
    ( '2018-04-02' ) /* This */
  , ( '2017-10-02' ) /* This */
  , ( '2018-04-02' ) /* Duplicate */
  , ( '2017-09-27' )
  , ( '2018-07-01' )
  , ( '2018-05-02' ) /* Same day, Diff DOW */
  , ( '2017-09-02' ) /* Same day, Diff DOW */
  , ( '2017-10-09' ) /* Diff day, Same DOW */
  , ( '2017-01-02' ) /* Same day, Same DOW, Earlier */
  , ( null )
;
我添加了几个案例,这些案例将在早期过滤器中被收集,但最终会被过滤掉。请参阅设置中的注释

主查询

DECLARE @enteredDate date = '2018-07-02' /* This is the date you entered. */

SELECT TOP 2 s1.testDate
FROM (
  SELECT t1.testDate
    , ROW_NUMBER() OVER ( PARTITION BY t1.testDate ORDER BY t1.testDate DESC, t1.id DESC  ) AS rn
  FROM t1
  INNER JOIN datedim dd ON t1.testDate = dd.theDate
    AND dd.theDay = DATEPART(day,@enteredDate)
    AND dd.theDOW = DATEPART(weekday,@enteredDate)
) s1
WHERE rn = 1 /* Get 1st result for a date. */
ORDER BY s1.testDate DESC
|   testDate |
|------------|
| 2018-04-02 |
| 2017-10-02 |
在主查询中,我们要做的第一件事是使用
ROW\u NUMBER()
窗口函数,确保如果存在重复的日期条目,我们只会得到一条记录。如果保证数据没有重复日期,则可以跳过此步骤

[结果][2]

DECLARE @enteredDate date = '2018-07-02' /* This is the date you entered. */

SELECT TOP 2 s1.testDate
FROM (
  SELECT t1.testDate
    , ROW_NUMBER() OVER ( PARTITION BY t1.testDate ORDER BY t1.testDate DESC, t1.id DESC  ) AS rn
  FROM t1
  INNER JOIN datedim dd ON t1.testDate = dd.theDate
    AND dd.theDay = DATEPART(day,@enteredDate)
    AND dd.theDOW = DATEPART(weekday,@enteredDate)
) s1
WHERE rn = 1 /* Get 1st result for a date. */
ORDER BY s1.testDate DESC
|   testDate |
|------------|
| 2018-04-02 |
| 2017-10-02 |

我认为这个问题是一个很好的例子,说明了日历表是多么有用。

02/10/2017
在周二。顺便问一下,您使用的是哪种DBMS?您使用的是什么数据库?SQL Server 2012您的日期维度中是否有一周中的某一天?谢谢。这个答案非常详细,帮助我实现了我想要做的事情。