Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/74.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_Postgresql - Fatal编程技术网

Sql 如何连接表,同时保留一个表上的确切信息?

Sql 如何连接表,同时保留一个表上的确切信息?,sql,postgresql,Sql,Postgresql,我想通过将一个表中的时间与第二个表中的时段(开始和结束时间)匹配来连接两个表,我需要这样做,以便操作保留一个表上的确切信息。更具体地说,我有这些表格 表t1: cid time1 A 2016-01-05 11:00:00 A 2016-01-15 11:00:00 A 2016-01-25 11:00:00 B 2016-01-09 11:00:00 表t2: cid period_start period_end A 201

我想通过将一个表中的时间与第二个表中的时段(开始和结束时间)匹配来连接两个表,我需要这样做,以便操作保留一个表上的确切信息。更具体地说,我有这些表格

表t1:

cid   time1
A     2016-01-05 11:00:00
A     2016-01-15 11:00:00
A     2016-01-25 11:00:00
B     2016-01-09 11:00:00
表t2:

cid   period_start          period_end
A     2016-01-01 00:00:00   2016-01-10 00:00:00
A     2016-01-10 00:00:00   2016-01-16 00:00:00
A     2016-01-12 00:00:00   2016-01-20 00:00:00
我希望输出为:

cid   time1                 period_start          period_end
A     2016-01-05 11:00:00   2016-01-01 00:00:00   2016-01-10 00:00:00
A     2016-01-15 11:00:00   2016-01-10 00:00:00   2016-01-16 00:00:00
A     2016-01-25 11:00:00   NULL                  NULL
B     2016-01-09 11:00:00   NULL                  NULL
一些附加信息/条件:

  • 我希望t1上的信息准确地保留在输出中(例如,t1上没有行连接到t2上的多行,t1中没有行在输出中丢失)。换句话说,我只想把t2中的信息作为列添加到t1中
  • 如果t2中没有包含t1上的time1的时段,我希望period_start和period_end为NULL
  • t2上可能根本没有匹配的cid
  • 如果t2上有多个匹配项,我只想要第一个
现在我有:

SELECT t1.*, t2.period_start, t2.period_end
FROM t1
  LEFT JOIN t2 ON t1.cid = t2.cid
WHERE t2.period_start >= t1.time1
AND t2.period_end <= t1.time1
选择t1.*,t2.period\u start,t2.period\u end
从t1开始
t1上的左连接t2.cid=t2.cid
其中t2.period\u start>=t1.time1

和t2.period_end将t2上的过滤器从where子句移动到join

FROM t1 LEFT JOIN t2 ep ON t1.cid = t2.cid
and t2.period_start >= t1.time1
AND t2.period_end <= t1.time1
从t1左侧连接t1.cid上的t2 ep=t2.cid
和t2.period\u start>=t1.time1

和t2.period_end您可以使用以下查询:

SELECT cid, time1, period_start, period_end
FROM (
   SELECT t1.cid, t1.time1, t2.period_start, t2.period_end,
          ROW_NUMBER() OVER (PARTITION BY t1.cid, t1.time1
                             ORDER BY t2.period_start) AS rn
   FROM t1
   LEFT JOIN t2 ON t1.cid = t2.cid AND 
                   t1.time1 BETWEEN t2.period_start AND t2.period_end) AS t
WHERE t.rn = 1            

ROW\u NUMBER
用于在多个匹配项的情况下从
t1
表中选择一条记录

因为您只需要
t2
中的第一个匹配行,所以可以使用带有
限制
子句的
横向
子查询:

SELECT t1.cid, t1.time1, t2.period_start, t2.period_end
FROM t1 LEFT JOIN LATERAL
     (SELECT *
      FROM t2
      WHERE cid=t1.cid AND t1.time1 BETWEEN period_start AND period_end
      ORDER BY t2.period_start
      LIMIT 1
     ) t2 ON true

这对我不起作用,因为t1中的1月15日连接到t2中的两行。我只想要第一个。