我找到了许多关于SELECT的问题和答案,排除了值为" NOT IN"子查询(例如this)。但是如何排除值列表而不是子查询?
我想搜索时间戳在某个范围内但排除某些特定日期时间的行。在英语中,那将是:
选择今天中午和下午2点之间记录的所有ORDER行,但以下时间除外:今天12:34,今天12:55,今天13:05。
SQL可能类似于:
SELECT *
FROM order_
WHERE recorded_ >= ?
AND recorded_ < ?
AND recorded_ NOT IN ( list of date-times… )
;
这个问题的两个部分:
PreparedStatement
设置任意数量的参数?答案 0 :(得分:3)
快速且安全的NULL替代方案是对未通过的数组LEFT JOIN
:
SELECT o.*
FROM order_ o
LEFT JOIN unnest(?::timestamp[]) x(recorded_) USING (recorded_)
WHERE o.recorded_ >= ?
AND o.recorded_ < ?
AND x.recorded_ IS NULL;
通过这种方式,您可以准备单个语句并将任意数量的时间戳作为数组传递。
只有在您无法输入参数时才需要显式转换::timestamp[]
(就像在prepared statements中一样)。该数组以单text
(或timestamp[]
)字面值传递:
'{2015-07-09 12:34, 2015-07-09 12:55, 2015-07-09 13:05}', ...
或者将CURRENT_DATE
放入查询并传递时间以添加outlined by @drake 。有关向time
添加interval
/ date
的更多信息:
您还可以使用VALUES
表达式或任何其他方法来创建特殊的值表。
SELECT o.*
FROM order_ o
LEFT JOIN (VALUES (?::timestamp), (?), (?) ) x(recorded_)
USING (recorded_)
WHERE o.recorded_ >= ?
AND o.recorded_ < ?
AND x.recorded_ IS NULL;
传递:
'2015-07-09 12:34', '2015-07-09 12:55', '2015-07-09 13:05', ...
这样您只能传递预定数量的时间戳。
对于最多100个参数(或您的max_function_args
设置),您可以使用带有VARIADIC
参数的服务器端函数:
我知道你知道timestamp
特征,但是对于普通大众来说:对于时间戳来说,相等匹配可能会很棘手,因为那些时间最多可以有6个小数位,你需要匹配准确
答案 1 :(得分:1)
SELECT *
FROM order_
WHERE recorded_ BETWEEN (CURRENT_DATE + time '12:00' AND CURRENT_DATE + time '14:00')
AND recorded_ NOT IN (CURRENT_DATE + time '12:34',
CURRENT_DATE + time '12:55',
CURRENT_DATE + time '13:05')
;