与当前数据匹配的SQL查找项

2024-04-28 22:45:37 发布

您现在位置:Python中文网/ 问答频道 /正文

下表(我们将其命名为有效期):

-------------------------------
id | valid_from  | valid_until
-------------------------------
1    2012-11-12    2012-12-02
2    2012-12-03    NULL
3    2012-12-15    2012-12-21

valid_from不可为null;valid_until可为null,但不必为null)

现在我想知道今天(2012-12-19)哪个条目是有效的。从逻辑的角度来看,它必须是条目3,因为条目可以相互重叠,但一天只有一个条目有效。(在2012年12月22日,它必须是有效的条目2。)
请注意,在之前,所有条目都可以有一个有效的,但不能有多个条目的valid_until为空。在

如何在SQL查询中执行此操作?(如果可能,在SQLAlchemy中,但我也可以自己从原始SQL翻译)

(我使用的是PostgreSQL 9.1)

编辑:这是我最后的决定。感谢所有投稿人! 在

^{pr2}$

Tags: from目的idsqlsqlalchemypostgresql条目逻辑
3条回答

作为示例,valid_until在您给出的数据中是逻辑冗余的,如果valid_from上存在索引,并且PostgreSQL将执行降序索引扫描,则使用此逻辑可能会获得更快的结果:

select   *
from     validity_period
where    valid_from <= current_date
order by valid_from desc
limit    1

检查explain计划,看看它是否是对更大数据集的改进。在

编辑:如果“最后一条”记录的有效截止日期早于今天,并且不返回任何行,请尝试:

^{pr2}$

最后一个谓词读起来可能更好:

where    not (most_recent_record.valid_until > current_date)

您可以使用窗口函数(例如lag或lead)引用上一个/下一个记录,并限制“打开”间隔:

DROP SCHEMA tmp CASCADE;
CREATE SCHEMA tmp ;
SET search_path=tmp;

CREATE TABLE daterange
        ( id INTEGER NOT NULL
        , valid_from  DATE NOT NULL
        , valid_until DATE
        );
INSERT INTO daterange (id, valid_from, valid_until) VALUES
 (1, '2012-11-12', '2012-12-02' )
,(2, '2012-12-03', NULL)
,(3, '2012-12-15', '2012-12-21' )
,(4, '2012-12-22', NULL )
        ;

-- The CTE is for convenience; could be a subquery or view
WITH magic AS (
        SELECT dr.id
        , dr.valid_from
        , COALESCE(dr.valid_until , lead(valid_from) OVER ww) AS valid_until
        FROM daterange dr
        WINDOW ww AS (ORDER BY dr.valid_from )
        )
SELECT *
FROM magic ma
WHERE now() BETWEEN ma.valid_from AND ma.valid_until
        ;

试试这样的方法:

SELECT  *
FROM    validity_period
WHERE   valid_from <= current_date
        AND valid_to >=current_date    
UNION 

--Gets the last instance where valid_until is null
SELECT * 
FROM validity_period 
WHERE   valid_from <= current_date
        AND valid_to IS NULL
ORDER BY id DESC LIMIT 1 

如果需要第一个而不是最后一个空字段,只需删除DESC

相关问题 更多 >