Bạn đã mắc lỗi đánh máy và viết date
thay vì date
nhưng bạn cũng cần thực hiện thay đổi thứ hai và sử dụng ADD_MONTHS
trong WHERE
của truy vấn đệ quy nếu không bạn sẽ tạo quá nhiều hàng.
WITH t1(test) AS (
SELECT MIN(alldates)
FROM dates
UNION ALL
SELECT ADD_MONTHS(test,1)
FROM t1
WHERE ADD_MONTHS(test,1) <= (SELECT MAX(alldates) FROM dates)
)
SELECT * FROM t1
Kết quả đầu ra:
Tuy nhiên, một truy vấn hiệu quả hơn sẽ là lấy các giá trị tối thiểu và tối đa trong cùng một truy vấn và sau đó lặp lại bằng cách sử dụng các giới hạn được tìm thấy trước sau:
WITH t1(min_date, max_date) AS (
SELECT MIN(alldates),
MAX(alldates)
FROM dates
UNION ALL
SELECT ADD_MONTHS(min_date,1),
max_date
FROM t1
WHERE ADD_MONTHS(min_date,1) <= max_date
)
SELECT min_date AS month
FROM t1
db <> fiddle tại đây
Cập nhật
Oracle 11gR2 có lỗi xử lý các truy vấn ngày đệ quy; điều này đã được khắc phục trong các phiên bản Oracle sau này nhưng nếu bạn muốn sử dụng SQL Fiddle và Oracle 11gR2 thì bạn cần phải lặp qua một giá trị số chứ không phải ngày tháng. Một cái gì đó như thế này:
Thiết lập lược đồ Oracle 11g R2 :
CREATE TABLE dates(
alldates date);
INSERT INTO dates (alldates) VALUES ('1-May-2017');
INSERT INTO dates (alldates) VALUES ('1-Mar-2018');
Truy vấn 1 :
WITH t1(min_date, month, total_months) AS (
SELECT MIN(alldates),
0,
MONTHS_BETWEEN(MAX(alldates),MIN(alldates))
FROM dates
UNION ALL
SELECT min_date,
month+1,
total_months
FROM t1
WHERE month+1<=total_months
)
SELECT ADD_MONTHS(min_date,month) AS month
FROM t1
Kết quả :
| MONTH |
|----------------------|
| 2017-05-01T00:00:00Z |
| 2017-06-01T00:00:00Z |
| 2017-07-01T00:00:00Z |
| 2017-08-01T00:00:00Z |
| 2017-09-01T00:00:00Z |
| 2017-10-01T00:00:00Z |
| 2017-11-01T00:00:00Z |
| 2017-12-01T00:00:00Z |
| 2018-01-01T00:00:00Z |
| 2018-02-01T00:00:00Z |
| 2018-03-01T00:00:00Z |