Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/84.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 从不同的表中查找最接近特定日期的表中的日期列表。_Sql_Sql Server - Fatal编程技术网

Sql 从不同的表中查找最接近特定日期的表中的日期列表。

Sql 从不同的表中查找最接近特定日期的表中的日期列表。,sql,sql-server,Sql,Sql Server,我在一个有日期列的表中有一个唯一ID的列表。例如: TABLE1 ID Date 0 2018-01-01 1 2018-01-05 2 2018-01-15 3 2018-01-06 4 2018-01-09 5 2018-01-12 6 2018-01-15 7 2018-01-02 8

我在一个有日期列的表中有一个唯一ID的列表。例如:

     TABLE1
 ID          Date
 0           2018-01-01
 1           2018-01-05
 2           2018-01-15
 3           2018-01-06
 4           2018-01-09
 5           2018-01-12
 6           2018-01-15
 7           2018-01-02
 8           2018-01-04
 9           2018-02-25
然后在另一个表中,我有一个不同值的列表,这些值针对每个ID和不同的日期多次出现

         TABLE 2
ID       Value       Date
0        18          2017-11-28
0        24          2017-12-29
0        28          2018-01-06
1        455         2018-01-03
1        468         2018-01-16
2        55          2018-01-03
3        100         2017-12-27
3        110         2018-01-04
3        119         2018-01-10
3        128         2018-01-30
4        223         2018-01-01
4        250         2018-01-09
4        258         2018-01-11

我想在表2中找到最接近表1中唯一日期的值。 有时表2确实包含一个与日期完全匹配的值,我在遍历这些值时没有遇到任何问题。但我无法计算出代码,以通过最接近表1中请求的日期的值

基于上述示例,我期望的结果是

ID          Value          Date
0           24             2017-12-29
1           455            2018-01-03
2           55             2018-01-03
3           110            2018-01-04
4           250            2018-01-09
因为我可以很容易地找到具有精确匹配的ID,所以我尝试过的一件事是将没有精确日期匹配的ID及其对应值放入临时表中。然后试图找到我需要的最接近的匹配值,但我不确定从哪里开始编码


抱歉,如果我缺少一个基本函数或子句,我还在学习

以下是一种方法:

WITH Table1 AS(
    SELECT ID, CONVERT(date, datecolumn) DateColumn
    FROM (VALUES (0,'20180101'),
                 (1,'20180105'),
                 (2,'20180115'),
                 (3,'20180106'),
                 (4,'20180109'),
                 (5,'20180112'),
                 (6,'20180115'),
                 (7,'20180102'),
                 (8,'20180104'),
                 (9,'20180225')) V(ID, DateColumn)),
Table2 AS(
    SELECT ID, [value], CONVERT(date, datecolumn) DateColumn
    FROM (VALUES (0,18 ,'2017-11-28'),
                 (0,24 ,'2017-12-29'),
                 (0,28 ,'2018-01-06'),
                 (1,455,'2018-01-03'),
                 (1,468,'2018-01-16'),
                 (2,55 ,'2018-01-03'),
                 (3,100,'2017-12-27'),
                 (3,110,'2018-01-04'),
                 (3,119,'2018-01-10'),
                 (3,128,'2018-01-30'),
                 (4,223,'2018-01-01'),
                 (4,250,'2018-01-09'),
                 (4,258,'2018-01-11')) V(ID, [Value],DateColumn))
SELECT T1.ID,
       T2.[Value],
       T2.DateColumn
FROM Table1 T1
     CROSS APPLY (SELECT TOP 1 *
                  FROM Table2 ca
                  WHERE T1.ID = ca.ID
                  ORDER BY ABS(DATEDIFF(DAY, ca.DateColumn, T1.DateColumn))) T2;

请注意,如果差异为天,则返回的行将是随机的(并且每次运行查询时可能会有所不同)。例如,如果
Table
具有日期
20180804
Table2
具有日期
20180803
20180805
它们都具有
ABS(DATEDIFF(DAY,ca.DateColumn,T1.DateColumn))的值
1
。因此,您可能需要在您的
订单中加入额外的逻辑,以确保一致的结果。

以下是一种方法:

WITH Table1 AS(
    SELECT ID, CONVERT(date, datecolumn) DateColumn
    FROM (VALUES (0,'20180101'),
                 (1,'20180105'),
                 (2,'20180115'),
                 (3,'20180106'),
                 (4,'20180109'),
                 (5,'20180112'),
                 (6,'20180115'),
                 (7,'20180102'),
                 (8,'20180104'),
                 (9,'20180225')) V(ID, DateColumn)),
Table2 AS(
    SELECT ID, [value], CONVERT(date, datecolumn) DateColumn
    FROM (VALUES (0,18 ,'2017-11-28'),
                 (0,24 ,'2017-12-29'),
                 (0,28 ,'2018-01-06'),
                 (1,455,'2018-01-03'),
                 (1,468,'2018-01-16'),
                 (2,55 ,'2018-01-03'),
                 (3,100,'2017-12-27'),
                 (3,110,'2018-01-04'),
                 (3,119,'2018-01-10'),
                 (3,128,'2018-01-30'),
                 (4,223,'2018-01-01'),
                 (4,250,'2018-01-09'),
                 (4,258,'2018-01-11')) V(ID, [Value],DateColumn))
SELECT T1.ID,
       T2.[Value],
       T2.DateColumn
FROM Table1 T1
     CROSS APPLY (SELECT TOP 1 *
                  FROM Table2 ca
                  WHERE T1.ID = ca.ID
                  ORDER BY ABS(DATEDIFF(DAY, ca.DateColumn, T1.DateColumn))) T2;
请注意,如果差异为天,则返回的行将是随机的(并且每次运行查询时可能会有所不同)。例如,如果
Table
具有日期
20180804
Table2
具有日期
20180803
20180805
它们都具有
ABS(DATEDIFF(DAY,ca.DateColumn,T1.DateColumn))的值
1
。因此,您可能需要在您的
订单中包含额外的逻辑,以确保一致的结果。

dude

我会说几件事让您考虑,因为SQL Server不是我的舒适区,而SQL本身是.< /P>


首先,我将每个ID连接TABLE1和TABLE2。这样,我可以在
SELECT
子句中指定以下元组:

SELECT ID, Value, DateDiff(d, T1.Date, T2.Date) qt_diff_days
显然,根据保存在那里的日期的精度,而不是它们是否有时间,您可以在
DateDiff
函数中更改日期字段

向前,我也将这个日期差设为绝对数(以解决正/负差异,只考虑经过时间)。 在那之后,这就是问题的症结所在,因为我不知道您使用的SQL Server版本,但基本上我会使用

行数
窗口函数按差异对所有行进行排序。如下所示:

SELECT
  ID, Value, Abs(DateDiff(d, T1.Date, T2.Date)) qt_diff_days,
  ROW_NUMBER() OVER(PARTITION BY ID ORDER BY Abs(DateDiff(d, T1.Date, T2.Date)) ASC) nu_row

对结果集的输出进行编号。更具体地说,返回结果集分区内一行的序列号,从每个分区中第一行的1开始

如果您可以正确运行
行号
,您应该注意到查询将按ID对其数据进行排序,从
1
开始,并根据两个日期之间的差异增加此排序,当ID更改时,将其排序重置为
1


之后,只需选择
nu_row
等于
1
的行。我会用CTE来解决这个问题

指定临时命名结果集,称为公共表表达式(CTE)

伙计

我会说几件事让您考虑,因为SQL Server不是我的舒适区,而SQL本身是.< /P>


首先,我将每个ID连接TABLE1和TABLE2。这样,我可以在
SELECT
子句中指定以下元组:

SELECT ID, Value, DateDiff(d, T1.Date, T2.Date) qt_diff_days
显然,根据保存在那里的日期的精度,而不是它们是否有时间,您可以在
DateDiff
函数中更改日期字段

向前,我也将这个日期差设为绝对数(以解决正/负差异,只考虑经过时间)。 在那之后,这就是问题的症结所在,因为我不知道您使用的SQL Server版本,但基本上我会使用

行数
窗口函数按差异对所有行进行排序。如下所示:

SELECT
  ID, Value, Abs(DateDiff(d, T1.Date, T2.Date)) qt_diff_days,
  ROW_NUMBER() OVER(PARTITION BY ID ORDER BY Abs(DateDiff(d, T1.Date, T2.Date)) ASC) nu_row

对结果集的输出进行编号。更具体地说,返回结果集分区内一行的序列号,从每个分区中第一行的1开始

如果您可以正确运行
行号
,您应该注意到查询将按ID对其数据进行排序,从
1
开始,并根据两个日期之间的差异增加此排序,当ID更改时,将其排序重置为
1


之后,只需选择
nu_row
等于
1
的行。我会用CTE来解决这个问题

指定临时命名结果集,称为公共表表达式(CTE)


如果您正在寻找1月2日,并且唯一可用的数据是1月1日和1月3日,您想要哪一个?你会考虑最大的距离吗?(如果最接近的值为+1年和-1年,您是否仍然想要其中一个?)您知道值之间的最大实际差距吗?(这将有助于优化对大型数据集的搜索)此外,您正在使用哪个版本的SQL Server?如果您正在查找1月2日的数据,并且唯一可用的数据是1月1日和1月3日,您希望使用哪个版本?你会考虑最大的距离吗?(如果最接近的值为+1年和-1年,您是否仍然想要其中一个?)您知道最大re值吗