Có một số cách để giải quyết vấn đề.
1. tạm thời thêm một cột
Như những người khác đã đề cập, cách thẳng về phía trước là để tạm thời thêm một cột reminder_id
đến dateset
. Điền nó với IDs
gốc từ bảng reminder
. Sử dụng nó để tham gia reminder
với bảng dateset
. Thả cột tạm thời.
2.khi bắt đầu là độc đáo
Nếu giá trị của cột start
là duy nhất chúng ta có thể làm điều đó mà không có cột thêm bằng cách tham gia reminder
bảng với bảng dateset
trên cột start
.
INSERT INTO dateset (start)
SELECT start FROM reminder;
WITH
CTE_Joined
AS
(
SELECT
reminder.id AS reminder_id
,reminder.dateset_id AS old_dateset_id
,dateset.id AS new_dateset_id
FROM
reminder
INNER JOIN dateset ON dateset.start = reminder.start
)
UPDATE CTE_Joined
SET old_dateset_id = new_dateset_id
;
3. khi bắt đầu là không độc đáo
Có thể làm điều đó mà không có cột tạm thời ngay cả trong trường hợp này. Ý tưởng chính là như sau. Chúng ta hãy có một cái nhìn vào ví dụ này:
Chúng tôi có hai hàng trong reminder
với cùng giá trị start
và ID 3 và 7:
reminder
id start dateset_id
3 2015-01-01 NULL
7 2015-01-01 NULL
Sau khi chúng tôi chèn chúng vào dateset
, sẽ có ID mới được tạo , ví dụ: 1 và 2:
dateset
id start
1 2015-01-01
2 2015-01-01
Việc chúng tôi liên kết hai hàng này không quan trọng. Kết quả cuối cùng có thể là
reminder
id start dateset_id
3 2015-01-01 1
7 2015-01-01 2
hoặc
reminder
id start dateset_id
3 2015-01-01 2
7 2015-01-01 1
Cả hai phiên bản là chính xác. Điều này đưa chúng ta đến giải pháp sau.
Chỉ cần chèn tất cả các hàng trước.
INSERT INTO dateset (start)
SELECT start FROM reminder;
Khớp/nối hai bảng trên start
khi biết rằng nó không phải là duy nhất. "Làm cho nó" độc đáo bằng cách thêm ROW_NUMBER
và tham gia bằng hai cột. Nó có thể làm cho các truy vấn ngắn hơn, nhưng tôi nêu ra từng bước một cách rõ ràng:
WITH
CTE_reminder_rn
AS
(
SELECT
id
,start
,dateset_id
,ROW_NUMBER() OVER (PARTITION BY start ORDER BY id) AS rn
FROM reminder
)
,CTE_dateset_rn
AS
(
SELECT
id
,start
,ROW_NUMBER() OVER (PARTITION BY start ORDER BY id) AS rn
FROM dateset
)
,CTE_Joined
AS
(
SELECT
CTE_reminder_rn.id AS reminder_id
,CTE_reminder_rn.dateset_id AS old_dateset_id
,CTE_dateset_rn.id AS new_dateset_id
FROM
CTE_reminder_rn
INNER JOIN CTE_dateset_rn ON
CTE_dateset_rn.start = CTE_reminder_rn.start AND
CTE_dateset_rn.rn = CTE_reminder_rn.rn
)
UPDATE CTE_Joined
SET old_dateset_id = new_dateset_id
;
Tôi hy vọng nó là rõ ràng từ mã những gì nó làm, đặc biệt là khi bạn so sánh nó với phiên bản đơn giản mà không ROW_NUMBER
. Rõ ràng, giải pháp phức tạp sẽ hoạt động ngay cả khi start
là duy nhất, nhưng nó không hiệu quả như một giải pháp đơn giản.
Giải pháp này giả định rằng dateset
trống trước quá trình này.
Làm cách nào để '2.' hoạt động? Có vẻ như biến thể này chỉ có thể hoạt động nếu CTE có thể được coi là lượt xem và được cập nhật.Tôi nghĩ tại thời điểm này, điều này là không thể ở bưu chính. –
@matthiaskrull, có vẻ như bạn đã đúng. Tôi đã sử dụng cú pháp SQL Server và tôi không có Postgres để kiểm tra. Trong Postgres bạn sẽ cần sử dụng mệnh đề 'FROM' trong câu lệnh [' UPDATE'] (http://www.postgresql.org/docs/9.4/static/sql-update.html) để nối các bảng. –