SQLite - 按给定间隔按日期存在选择行

时间:2018-03-13 22:06:46

标签: sql sqlite

我有一个带有两个表的sqlite3数据库,如下所示:

Table: Position
| pk | name | ...
------------------
| 1  | pos1 | ...
| 2  | pos2 | ...


Table: Status
| pk_position | datetime | ...
----------------------
| 1           | 20170201 | ...
| 1           | 20170204 | ...
| 1           | 20170205 | ...
| 1           | 20170207 | ...
| 2           | 20170204 | ...
| 2           | 20170201 | ...
| 2           | 20170208 | ...

其中datetime为“YYYYMMDD”(即%Y%m%d),pk_position是表位置的ForeginKey。

我需要以下内容:给定两个时间间隔int1 = [day1:day2]int2 = [day3:day4],我想要一个唯一的pk_position选项,其中至少有一行datetime包含在每个区间内。

示例(使用示例表):

  • int1 = ["20170201" : "20170202"]int2 = ["20170202" : "20170203"] => (空)

  • int1 = ["20170204" : "20170205"]int2 = ["20170205" : "20170206"] => 1

  • int1 = ["20170203" : "20170204"]int2 = ["20170204" : "20170205"] => 1,2

我尝试使用EXISTS,但我找不到任何明智的方法来实现这一目标。

谢谢!

OBS :我试图让问题尽可能广泛。实际上,在我的所有用例中,区间将具有[day1:day2],[day2:day3]的形式(即它们共享一个共同的边界),就像所有示例一样。如果为共同边界这样做更容易,我会很高兴解决这个更简单的问题。

1 个答案:

答案 0 :(得分:0)

我认为这会让你到那里(我没有办法测试SQLite,所以如果没有逗号,或者分号错了,或者分号错了,我就不会感到惊讶,或者类似的东西,但这是SQL中的逻辑,在没有最终测试的情况下尽可能地适应SQLite):

CREATE TEMP TABLE 
    _time_intervals
    (
    int1 TEXT, 
    int2 TEXT, 
    int1Start TEXT, 
    int1End TEXT, 
    int2Start TEXT, 
    int2End TEXT
    );

INSERT INTO 
    _time_intervals(int1, int2) 
    VALUES ( '["20170201" : "20170202"]', '["20170202" : "20170203"]' );

UPDATE _time_intervals
    SET int1Start = SUBSTR(int1, 3, 8),
    SET int1End = SUBSTR(int1, 16, 8),
    SET int2Start = SUBSTR(int2, 3, 8),
    SET int2End = SUBSTR(int2, 16, 8)

SELECT
    pk_position
FROM
(
SELECT
    s.pk_position,
    1 AS int1_counter,
    0 AS int2_counter
FROM
    Status AS s
WHERE
    s.datetime BETWEEN (SELECT int1Start FROM _time_intervals) AND  (SELECT int1End FROM _time_intervals)
UNION ALL
SELECT
    s.pk_position,
    0 AS int1_counter,
    1 AS int2_counter
FROM
    Status AS s
WHERE
    s.datetime BETWEEN  (SELECT int2Start FROM _time_intervals) AND  (SELECT int2End FROM _time_intervals)
) AS sq
GROUP BY 
    pk_position
HAVING
    SUM(int1_counter) > 0
AND
    SUM(int2_counter) > 0;

DROP TABLE _time_intervals;