items
。其中的列是一些唯一的id,位置和旧位置。
如果它具有旧位置,则其当前从position_old
移动到position
。如果它的位置-
为旧
它不动。每个职位可以有多个项目。
第二个表(position
)用于职位。其中的列是唯一的ID和状态。
我需要更新位置表中状态为100且没有移动到其中的项目的所有行
(position = position_id AND position_old != '-'
)并且没有项目从中移动(position_old = position_id
)。
+---------+----------+--------------+
| item_id | position | position_old |
+---------+----------+--------------+
| 1 | 0001 | - |
| 2 | 0001 | 0002 |
+---------+----------+--------------+
+-------------+--------+
| position_id | status |
+-------------+--------+
| 0001 | 0 |
| 0002 | 100 |
+-------------+--------+
我得到了一些解决方案,但我认为它不是最好的解决方案:
UPDATE Position
SET status = 0
WHERE status = 100
AND position_id NOT IN (
SELECT DISTINCT position_old FROM Items WHERE position_old != '-'
UNION
SELECT DISTINCT position FROM Items WHERE position_old != '-'
)
那么还有更好的方法吗?仅供参考 它是一个Oracle 11.2.0.4数据库,如果你建议使用连接,那么每个人都应该使用糟糕的旧语法 这是与它合作,不愿意学习更新的标准。
答案 0 :(得分:0)
我认为更高效的是:
UPDATE Position out_pos
SET status = 0
WHERE status = 100
AND not exists (
SELECT 1 FROM Items sub_pos WHERE
sub_pos.position_old != '-' and
(
sub_pos.position = out_pos.position_id
OR
sub_pos.position_old = out_pos.position_id
)
)
答案 1 :(得分:0)
你的陈述是正确的,但我更愿意用“不存在”来写它以匹配自然语言形式:
UPDATE Position
SET status = 0
WHERE
-- which have status 100:
status = 100
AND
-- have no item which is moving to it:
NOT EXISTS (SELECT * FROM items WHERE position = position_id AND position_old <> '-')
AND
-- no item moving from it:
NOT EXISTS (SELECT * FROM items WHERE position_old = position_id)
至于效率,执行该声明并查看执行计划是无可替代的。根据索引的存在,表格的基数和条件的选择性(以及更多......),Oracle将乐意将“EXISTS”重写为“IN”等等。
items
上带有position_old, position
列(按此顺序)的索引似乎很有帮助。