英文:
Translate Oracle query to H2
问题
以下是翻译好的部分:
我有以下查询,在Oracle中运行良好:
此查询返回当前月份的所有日期列表。
问题在于我需要此查询在H2中也能工作,但H2不支持“LEVEL”、“TRUNC”或“CONNECT BY”。因此,我该如何重写查询,以使其在Oracle和H2中都能正常工作?
英文:
I have the following query, which works fine in Oracle:
SELECT TRUNC(CURRENT_DATE, 'MM') + LEVEL - 1 AS MYDATE FROM DUAL CONNECT BY LEVEL <= EXTRACT(DAY FROM LAST_DAY(CURRENT_DATE));
This query returns a list with all the days from current month.
The issue is that I need this query to also work in H2, but H2 does not support LEVEL
or TRUNC
or CONNECT BY
. Therefore, how could I rewrite the query so that it works with both Oracle and H2?
答案1
得分: 2
以下是翻译好的内容:
You can use the following query with both Oracle and H2:
WITH T(MYDATE) AS (
SELECT CAST(TRUNC(CURRENT_DATE)
- INTERVAL '1' DAY * (EXTRACT(DAY FROM CURRENT_DATE) - 1) AS DATE) MYDATE
FROM DUAL
UNION ALL
SELECT CAST(MYDATE AS DATE) + INTERVAL '1' DAY
FROM T
WHERE EXTRACT(MONTH FROM CAST(MYDATE AS DATE) + INTERVAL '1' DAY)
= EXTRACT(MONTH FROM CURRENT_DATE)
)
SELECT MYDATE FROM T;
But if you can use different queries, it will be better to use that one with H2:
SELECT DATE_TRUNC(MONTH, CURRENT_DATE) + INTERVAL '1' DAY * X MYDATE
FROM SYSTEM_RANGE(0, EXTRACT(DAY FROM
DATE_TRUNC(MONTH, CURRENT_DATE) + INTERVAL '1' MONTH - INTERVAL '2' DAY));
(In future versions of H2 it will be possible to use a simpler query.)
英文:
You can use the following query with both Oracle and H2:
WITH T(MYDATE) AS (
SELECT CAST(TRUNC(CURRENT_DATE)
- INTERVAL '1' DAY * (EXTRACT(DAY FROM CURRENT_DATE) - 1) AS DATE) MYDATE
FROM DUAL
UNION ALL
SELECT CAST(MYDATE AS DATE) + INTERVAL '1' DAY
FROM T
WHERE EXTRACT(MONTH FROM CAST(MYDATE AS DATE) + INTERVAL '1' DAY)
= EXTRACT(MONTH FROM CURRENT_DATE)
)
SELECT MYDATE FROM T;
But if you can use different queries, it will be better to use that one with H2:
SELECT DATE_TRUNC(MONTH, CURRENT_DATE) + INTERVAL '1' DAY * X MYDATE
FROM SYSTEM_RANGE(0, EXTRACT(DAY FROM
DATE_TRUNC(MONTH, CURRENT_DATE) + INTERVAL '1' MONTH - INTERVAL '2' DAY));
(In future versions of H2 it will be possible to use a simpler query.)
答案2
得分: 1
不容易。比较Oracle和H2函数:
- Oracle支持
TRUNC
,H2支持DATE_TRUNC
- Oracle支持
LAST_DAY
,而H2不支持。
H2似乎支持EXTRACT
和CAST
函数,如果它支持递归查询,那么您可以仅使用这些函数编写一些内容(但不够优雅):
WITH days (day, month) AS (
SELECT CURRENT_DATE
- EXTRACT(DAY FROM CURRENT_DATE) + 1
- EXTRACT(HOUR FROM CAST(CURRENT_TIMESTAMP AS TIMESTAMP)) / 24
- EXTRACT(MINUTE FROM CURRENT_TIMESTAMP) / 24 / 60
- FLOOR(EXTRACT(SECOND FROM CURRENT_TIMESTAMP)) / 24 / 60 / 60,
EXTRACT(MONTH FROM CURRENT_DATE)
FROM DUAL
UNION ALL
SELECT day + 1,
month
FROM days
WHERE EXTRACT(MONTH FROM day + 1) = month
)
SELECT day
FROM days;
或者,如果H2不支持将数字添加到日期,则可以使用INTERVAL
:
WITH days (day, month) AS (
SELECT CURRENT_DATE
- INTERVAL '1' DAY * (EXTRACT(DAY FROM CURRENT_DATE) - 1)
- INTERVAL '1' HOUR * EXTRACT(HOUR FROM CAST(CURRENT_TIMESTAMP AS TIMESTAMP))
- INTERVAL '1' MINUTE * EXTRACT(MINUTE FROM CURRENT_TIMESTAMP)
- INTERVAL '1' SECOND * FLOOR(EXTRACT(SECOND FROM CURRENT_TIMESTAMP)),
EXTRACT(MONTH FROM CURRENT_DATE)
FROM DUAL
UNION ALL
SELECT day + INTERVAL '1' DAY,
month
FROM days
WHERE EXTRACT(MONTH FROM day + INTERVAL '1' DAY) = month
)
SELECT day
FROM days;
这两种方法都会输出:
DAY |
---|
2023-06-01 00:00:00 |
2023-06-02 00:00:00 |
2023-06-03 00:00:00 |
... |
2023-06-29 00:00:00 |
2023-06-30 00:00:00 |
我无法访问H2实例来测试它是否在该RDBMS上运行。
然而,您可能会发现编写针对每个数据库的不同代码比尝试重用相同的代码更简单。
英文:
> how could I rewrite the query so that it works with both Oracle and H2?
Not easily. Comparing Oracle and H2 functions:
- Oracle supports
TRUNC
and H2 supportsDATE_TRUNC
- Oracle supports
LAST_DAY
and H2 does not.
H2 appears to support the functions EXTRACT
and CAST
and if it supports recursive queries then you could write something using only those functions (but it is not nice):
WITH days (day, month) AS (
SELECT CURRENT_DATE
- EXTRACT(DAY FROM CURRENT_DATE) + 1
- EXTRACT(HOUR FROM CAST(CURRENT_TIMESTAMP AS TIMESTAMP)) / 24
- EXTRACT(MINUTE FROM CURRENT_TIMESTAMP) / 24 / 60
- FLOOR(EXTRACT(SECOND FROM CURRENT_TIMESTAMP)) / 24 / 60 / 60,
EXTRACT(MONTH FROM CURRENT_DATE)
FROM DUAL
UNION ALL
SELECT day + 1,
month
FROM days
WHERE EXTRACT(MONTH FROM day + 1) = month
)
SELECT day
FROM days;
or, if H2 does not support adding numbers to dates then you can use INTERVAL
s:
WITH days (day, month) AS (
SELECT CURRENT_DATE
- INTERVAL '1' DAY * (EXTRACT(DAY FROM CURRENT_DATE) - 1)
- INTERVAL '1' HOUR * EXTRACT(HOUR FROM CAST(CURRENT_TIMESTAMP AS TIMESTAMP))
- INTERVAL '1' MINUTE * EXTRACT(MINUTE FROM CURRENT_TIMESTAMP)
- INTERVAL '1' SECOND * FLOOR(EXTRACT(SECOND FROM CURRENT_TIMESTAMP)),
EXTRACT(MONTH FROM CURRENT_DATE)
FROM DUAL
UNION ALL
SELECT day + INTERVAL '1' DAY,
month
FROM days
WHERE EXTRACT(MONTH FROM day + INTERVAL '1' DAY) = month
)
SELECT day
FROM days;
Which both output:
DAY |
---|
2023-06-01 00:00:00 |
2023-06-02 00:00:00 |
2023-06-03 00:00:00 |
... |
2023-06-29 00:00:00 |
2023-06-30 00:00:00 |
I don't have access to a H2 instance to test whether it works on that RDBMS.
However, you may find it simpler to write different code for each database rather than trying to re-use the same code.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论