Oracle SQL:检查时间是否在两个实例之间(不包括dd/mm/yyyy)
Oracle SQL: check if time is between two instances (excluding dd/mm/yyyy)
我正在构建一个 Oracle APEX 应用程序,记者可以在其中引入文章,导演 select 负责广播,还有新闻阅读器(如果创建了广播,他可以阅读文章)。我有点坚持以下几点:
我想创建一个 Oracle SQL 查询,其中 select 是 "user" table 中记录的名字和姓氏,当它可用时(存储在另一个table, "Beschikbaarheid") 满足给定的情况(广播日用户开始时间 >= 广播开始时间 AND 用户广播日结束时间 <= 广播结束时间)。
我自己写了以下查询。
SELECT voornaam || ' ' || achternaam AS display_value, id AS return_value
FROM Gebruiker
WHERE id NOT IN (SELECT Nieuwslezerselectie.nieuwslezerid FROM Nieuwslezerselectie
WHERE -- other conditions
AND id IN (SELECT gebruikerid
FROM Beschikbaarheid
WHERE (dag = to_char(to_date(:P91_DATUM,'DD-MON-YYYY'),'Day'))
AND (to_date(:P91_BEGINTIJD,'HH24:MI') >= to_date(begintijd,'HH24:MI'))
AND (to_date(:P91_EINDTIJD,'HH24:MI') <= to_date(eindtijd,'HH24:MI'))
);
(如果您阅读本文时遇到问题,请原谅,我使用的是荷兰语命名。如果有任何不清楚的地方,请随时询问。)
但是,如果新闻阅读器在广播时可用,则此查询链接到的 APEX select 列表不会显示任何内容。我认为问题是 "Begintijd" 和 "Eindtijd" 存储为时间戳,因为值应该与日期无关(时间戳不是),但我不知道如何存储它们。也许作为 varchar?
真诚希望您有任何想法。提前致谢!
吕克
更新 1
在帮助下我重写了查询,现在看起来像这样:
AND id IN (SELECT gebruikerid
FROM Beschikbaarheid
WHERE (dag = to_char(to_date(:P91_DATUM,'DD-MON-YYYY'),'Day','NLS_DATE_LANGUAGE=Dutch'))
AND (
to_date('01-01-2000' || ' ' || to_char(to_timestamp(:P91_BEGINTIJD),'HH24:MI'),'DD-MM-YYYY HH24:MI')
BETWEEN
to_date('01-01-2000' || ' ' || to_char(begintijd,'HH24:MI'),'DD-MM-YYYY HH24:MI')
AND
to_date('01-01-2000' || ' ' || to_char(eindtijd,'HH24:MI'),'DD-MM-YYYY HH24:MI')
)
AND (
to_date('01-01-2000' || ' ' || to_char(to_timestamp(:P91_EINDTIJD),'HH24:MI'),'DD-MM-YYYY HH24:MI')
BETWEEN
to_date('01-01-2000' || ' ' || to_char(begintijd,'HH24:MI'),'DD-MM-YYYY HH24:MI')
AND
to_date('01-01-2000' || ' ' || to_char(eindtijd,'HH24:MI'),'DD-MM-YYYY HH24:MI')
)
);
但是,我现在在尝试访问该页面时收到 ORA-01840:输入值的日期格式不够长 错误。我还没有发现导致该错误的原因。有人有线索吗?
更新 2
现在我很困惑。结果我的页面变量不需要 to_char 等,所以我删除了那些(to_char 等)。现在我通常发送到正确的页面,但我在上一页的 "set these items / with these values" 文本字段中输入的最后一个值没有发送。这是我现在在这些文本字段中的内容:
在此图像中,P85_BEGINTIJD 未发送。我也改变了价值观,但这并没有什么不同。您可以通过请求或其他方式发送的值的数量是否有限制?
不要使用时间戳。 se 一个日期字段,其中包括日期和时间,
有关 oracle 中日期字段的更多信息:
Oracle Data types, see paragraph Overview of DATE Datatype
如果我没看错,你有两列数据类型为 TIMESTAMP,你需要使用参数 对其进行约束,但每分钟仅使用小时 一部分。
最简单的方法是使用 HH:MI
格式的字符串参数
select begintijd, to_char(begintijd,'HH24:MI') begintijd_hhmi,
eindtijd, to_char(eindtijd,'HH24:MI') eindtijd_hhmi from tst
where '22:00' between to_char(begintijd,'HH24:MI') and to_char(eindtijd,'HH24:MI')
;
请注意,您使用 to_char 和日期掩码 HH24:MI 来删除不相关的部分date/time.
可能更好、更灵活的方法是使用 INTERVALs。
with t2 as (
select
begintijd, begintijd - trunc(begintijd) begintijd_hhmi,
eindtijd, eindtijd - trunc(eindtijd) eindtijd_hhmi from tst)
select * from t2
where INTERVAL '22:00' HOUR TO MINUTE between begintijd_hhmi and eindtijd_hhmi
;
您使用时间戳和截断时间戳的差来计算间隔(小时和分钟)。但请注意,如果时间戳可以包含秒或它的分数,您可能需要 trim 它们,例如与
NumToDsInterVal(60*extract(hour from begintijd)+extract(minute from begintijd),'MINUTE') begintijd_hhmi
好吧,最终我解决了这个问题。在我的上次更新中,唯一持续存在的问题是某些变量没有发送到下一页。我找不到问题的根本原因,所以我做了一个解决方法。
唯一正常发送到下一页的变量是P91_UITZENDING(Uitzending的PK)。幸运的是,我需要的其他变量(begintijd、eindtijd 和 datum)是 Uitzending 的属性,因此我能够在相应页面项目的源代码中使用如下语句导出它们:
SELECT to_char(begintijd,'HH24:MI')
-- replace with eindtijd for eindtijd, and for date: to_char(datum,'DD-MON-YYYY')
FROM Uitzending
WHERE id = :P91_UITZENDING
最后 SQL 对 select 框的查询:
SELECT voornaam || ' ' || achternaam AS display_value, id AS return_value
FROM Gebruiker
WHERE -- Other statements
AND id IN (SELECT gebruikerid
FROM Beschikbaarheid
WHERE (dag = to_char(to_date(:P91_DATUM,'DD-MON-YYYY'),'fmDay','NLS_DATE_LANGUAGE=Dutch'))
AND (
to_date('01-01-2000' || :P91_BEGINTIJD,'DD-MM-YYYY HH24:MI')
BETWEEN
to_date('01-01-2000' || to_char(begintijd,'HH24:MI'),'DD-MM-YYYY HH24:MI')
AND
to_date('01-01-2000' || to_char(eindtijd,'HH24:MI'),'DD-MM-YYYY HH24:MI')
)
AND (
to_date('01-01-2000' || :P91_EINDTIJD,'DD-MM-YYYY HH24:MI')
BETWEEN
to_date('01-01-2000' || to_char(begintijd,'HH24:MI'),'DD-MM-YYYY HH24:MI')
AND
to_date('01-01-2000' || to_char(eindtijd,'HH24:MI'),'DD-MM-YYYY HH24:MI')
)
);
我仍然不知道为什么 begintijd、eindtijd 和 datum 没有以正常方式发送,但至少它现在可以工作了。
感谢大家的思考和帮助!
我正在构建一个 Oracle APEX 应用程序,记者可以在其中引入文章,导演 select 负责广播,还有新闻阅读器(如果创建了广播,他可以阅读文章)。我有点坚持以下几点:
我想创建一个 Oracle SQL 查询,其中 select 是 "user" table 中记录的名字和姓氏,当它可用时(存储在另一个table, "Beschikbaarheid") 满足给定的情况(广播日用户开始时间 >= 广播开始时间 AND 用户广播日结束时间 <= 广播结束时间)。
我自己写了以下查询。
SELECT voornaam || ' ' || achternaam AS display_value, id AS return_value
FROM Gebruiker
WHERE id NOT IN (SELECT Nieuwslezerselectie.nieuwslezerid FROM Nieuwslezerselectie
WHERE -- other conditions
AND id IN (SELECT gebruikerid
FROM Beschikbaarheid
WHERE (dag = to_char(to_date(:P91_DATUM,'DD-MON-YYYY'),'Day'))
AND (to_date(:P91_BEGINTIJD,'HH24:MI') >= to_date(begintijd,'HH24:MI'))
AND (to_date(:P91_EINDTIJD,'HH24:MI') <= to_date(eindtijd,'HH24:MI'))
);
(如果您阅读本文时遇到问题,请原谅,我使用的是荷兰语命名。如果有任何不清楚的地方,请随时询问。)
但是,如果新闻阅读器在广播时可用,则此查询链接到的 APEX select 列表不会显示任何内容。我认为问题是 "Begintijd" 和 "Eindtijd" 存储为时间戳,因为值应该与日期无关(时间戳不是),但我不知道如何存储它们。也许作为 varchar?
真诚希望您有任何想法。提前致谢!
吕克
更新 1
在帮助下我重写了查询,现在看起来像这样:
AND id IN (SELECT gebruikerid
FROM Beschikbaarheid
WHERE (dag = to_char(to_date(:P91_DATUM,'DD-MON-YYYY'),'Day','NLS_DATE_LANGUAGE=Dutch'))
AND (
to_date('01-01-2000' || ' ' || to_char(to_timestamp(:P91_BEGINTIJD),'HH24:MI'),'DD-MM-YYYY HH24:MI')
BETWEEN
to_date('01-01-2000' || ' ' || to_char(begintijd,'HH24:MI'),'DD-MM-YYYY HH24:MI')
AND
to_date('01-01-2000' || ' ' || to_char(eindtijd,'HH24:MI'),'DD-MM-YYYY HH24:MI')
)
AND (
to_date('01-01-2000' || ' ' || to_char(to_timestamp(:P91_EINDTIJD),'HH24:MI'),'DD-MM-YYYY HH24:MI')
BETWEEN
to_date('01-01-2000' || ' ' || to_char(begintijd,'HH24:MI'),'DD-MM-YYYY HH24:MI')
AND
to_date('01-01-2000' || ' ' || to_char(eindtijd,'HH24:MI'),'DD-MM-YYYY HH24:MI')
)
);
但是,我现在在尝试访问该页面时收到 ORA-01840:输入值的日期格式不够长 错误。我还没有发现导致该错误的原因。有人有线索吗?
更新 2
现在我很困惑。结果我的页面变量不需要 to_char 等,所以我删除了那些(to_char 等)。现在我通常发送到正确的页面,但我在上一页的 "set these items / with these values" 文本字段中输入的最后一个值没有发送。这是我现在在这些文本字段中的内容:
在此图像中,P85_BEGINTIJD 未发送。我也改变了价值观,但这并没有什么不同。您可以通过请求或其他方式发送的值的数量是否有限制?
不要使用时间戳。 se 一个日期字段,其中包括日期和时间, 有关 oracle 中日期字段的更多信息: Oracle Data types, see paragraph Overview of DATE Datatype
如果我没看错,你有两列数据类型为 TIMESTAMP,你需要使用参数 对其进行约束,但每分钟仅使用小时 一部分。
最简单的方法是使用 HH:MI
格式的字符串参数 select begintijd, to_char(begintijd,'HH24:MI') begintijd_hhmi,
eindtijd, to_char(eindtijd,'HH24:MI') eindtijd_hhmi from tst
where '22:00' between to_char(begintijd,'HH24:MI') and to_char(eindtijd,'HH24:MI')
;
请注意,您使用 to_char 和日期掩码 HH24:MI 来删除不相关的部分date/time.
可能更好、更灵活的方法是使用 INTERVALs。
with t2 as (
select
begintijd, begintijd - trunc(begintijd) begintijd_hhmi,
eindtijd, eindtijd - trunc(eindtijd) eindtijd_hhmi from tst)
select * from t2
where INTERVAL '22:00' HOUR TO MINUTE between begintijd_hhmi and eindtijd_hhmi
;
您使用时间戳和截断时间戳的差来计算间隔(小时和分钟)。但请注意,如果时间戳可以包含秒或它的分数,您可能需要 trim 它们,例如与
NumToDsInterVal(60*extract(hour from begintijd)+extract(minute from begintijd),'MINUTE') begintijd_hhmi
好吧,最终我解决了这个问题。在我的上次更新中,唯一持续存在的问题是某些变量没有发送到下一页。我找不到问题的根本原因,所以我做了一个解决方法。
唯一正常发送到下一页的变量是P91_UITZENDING(Uitzending的PK)。幸运的是,我需要的其他变量(begintijd、eindtijd 和 datum)是 Uitzending 的属性,因此我能够在相应页面项目的源代码中使用如下语句导出它们:
SELECT to_char(begintijd,'HH24:MI')
-- replace with eindtijd for eindtijd, and for date: to_char(datum,'DD-MON-YYYY')
FROM Uitzending
WHERE id = :P91_UITZENDING
最后 SQL 对 select 框的查询:
SELECT voornaam || ' ' || achternaam AS display_value, id AS return_value
FROM Gebruiker
WHERE -- Other statements
AND id IN (SELECT gebruikerid
FROM Beschikbaarheid
WHERE (dag = to_char(to_date(:P91_DATUM,'DD-MON-YYYY'),'fmDay','NLS_DATE_LANGUAGE=Dutch'))
AND (
to_date('01-01-2000' || :P91_BEGINTIJD,'DD-MM-YYYY HH24:MI')
BETWEEN
to_date('01-01-2000' || to_char(begintijd,'HH24:MI'),'DD-MM-YYYY HH24:MI')
AND
to_date('01-01-2000' || to_char(eindtijd,'HH24:MI'),'DD-MM-YYYY HH24:MI')
)
AND (
to_date('01-01-2000' || :P91_EINDTIJD,'DD-MM-YYYY HH24:MI')
BETWEEN
to_date('01-01-2000' || to_char(begintijd,'HH24:MI'),'DD-MM-YYYY HH24:MI')
AND
to_date('01-01-2000' || to_char(eindtijd,'HH24:MI'),'DD-MM-YYYY HH24:MI')
)
);
我仍然不知道为什么 begintijd、eindtijd 和 datum 没有以正常方式发送,但至少它现在可以工作了。
感谢大家的思考和帮助!