我正在寻找一些帮助,根据以下规则编写数据转换SQL脚本(或者PL / SQL脚本?)。
For each person...
1) If all three tasks are 'done', do nothing
2) If 'wake up' task is 'awaiting', do nothing
3) Else, INSERT a new record for person WHERE item = 'go to work'
and status = 'awaiting'
tasks table:
id person item status
1 john wake up done
2 john brush teeth done
3 john get dressed done
4 amy wake up done
5 amy brush teeth done
6 amy get dressed done
7 frank wake up awaiting
8 sue wake up done
9 sue brush teeth started
10 andy wake up done
11 andy brush teeth started
12 andy get dressed started
...
...
...
虽然我有一些SQL经验,但我刚开始学习PL / SQL。我相信这里可能需要PL / SQL来遍历每个人,检查人员记录,并应用IF THEN逻辑。
这是我到目前为止所做的:
BEGIN
FOR task IN (SELECT DISTINCT person
FROM tasks)
LOOP
DBMS_OUTPUT.PUT_LINE('Processing... ' || task.person || ', ' || task.item || ', ' || task.status);
-- This is where I am having trouble.
-- How can I examine all rows for each candidate
-- at once when each row is returned only one at a time?
END LOOP;
END;
答案 0 :(得分:0)
INSERT INTO tasks
SELECT MYSEQ.NEXTVAL,Person,item,status
FROM
(
SELECT person,
'go to work' AS item
'AWAITING' as status
FROM tasks
GROUP BY person
HAVING COUNT(DECODE(status,'AWAITING',1)) = 0 AND COUNT(*) <> 3
) MYVIEW
希望像这样的查询,对你有帮助吗?
仍然,对于PL / SQL解决方案:
BEGIN
FOR task IN (SELECT DISTINCT person
FROM tasks)
LOOP
DBMS_OUTPUT.PUT_LINE('Processing... ' || task.person || ', ' || task.item || ', ' || task.status);
INSERT INTO tasks
SELECT
MYSEQ.NEXTVAL,
task.person,
'go to work',
'AWAITING'
FROM dual
WHERE NOT EXISTS
(SELECT 'x' FROM tasks t
WHERE t.person = task.person AND t.status = 'AWAITING');
DBMS_OUTPUT.PUT_LINE(TO_CHAR(SQL%ROWCOUNT) || ' rows inserted.');
END LOOP;
COMMIT;
END;
答案 1 :(得分:0)
您可以根据需要使用以下SQL查询插入新行。可以使用PL / SQL将相同的逻辑构建到循环中,但基于集合的SQL处理比循环和逐个记录处理要快得多。
以下查询假定您有一个BEFORE INSERT触发器,它从序列中获取下一个值以更新id列。
INSERT INTO tasks (person, item, status)
SELECT
person, 'go to work', 'awaiting'
FROM persons
WHERE (task = 'wake up' AND status <> 'awaiting')
OR person in
(
SELECT
person
FROM tasks
WHERE status = 'done'
GROUP BY person
HAVING count(*) <> 3
) persons_done;
否则,您可以手动从序列中获取下一个值,如:
INSERT INTO tasks (id, person, item, status)
SELECT
my_sequence.nextVal, person, 'go to work', 'awaiting' --Replace my_sequence with the name of the sequence in your database
FROM persons
WHERE (task = 'wake up' AND status <> 'awaiting')
OR person in
(
SELECT
person
FROM tasks
WHERE status = 'done'
GROUP BY person
HAVING count(*) <> 3
) persons_done;
<强>参考强>:
Thanks for the question regarding "Cursors or queries?", version 9.2.0 on AskTom Oracle