如果有可能请帮帮我:)我想写一个更新语句(无循环):
CARD_NO_MAP:
PREFIX CARD_NO NEW_CARD_NO
---------------------------
555 000000 NULL
555 111111 NULL
555 222222 NULL
555 333333 NULL
555 444444 NULL
555 555555 NULL
555 666666 NULL
666 111111 NULL
666 222222 NULL
666 333333 NULL
666 444444 NULL
CARDS:
CARD_NO
-----------
1231263
1234566
1236547
1236549
4564566
4560001
4561234
如果不清楚它的作用,我会尝试解释。
修改
一开始我们有这样的事情:
CARD_NO_MAP
更新后的PREFIX CARD_NO NEW_CARD_NO
---------------------------
555 000000 1231263
555 111111 1234566
555 222222 1236547
555 333333 1236549
555 444444 NULL
555 555555 NULL
555 666666 NULL
666 111111 4564566
666 222222 4560001
666 333333 4561234
666 444444 NULL
:
CARDS.CARD_NO
每个PREFIX || CARD_NO
都与CARD_NO_MAP
表中唯一的cd /home/*your_app_name*/app/programs/server/npm/mode_modules/meteor/npm-bcrypt
npm install bcrypt
唯一一样唯一。 (不要问为什么会这样做......)
答案 0 :(得分:1)
不同的,可以说更简单的方法是使用合并。您无法合并到视图中,但可以通过连接两个表并对结果应用密集排名分析函数来创建映射:
select cnm.prefix, cnm.card_no, c.card_no as new_card_no,
dense_rank() over (partition by cnm.prefix order by c.card_no) rnk1,
dense_rank() over (partition by c.card_no order by cnm.prefix, cnm.card_no) rnk2
from card_no_map cnm
join cards c
on case when c.card_no like '123%' then 555
when c.card_no like '456%' then 666
else -1 end = cnm.prefix
where cnm.new_card_no is null;
PREFIX CARD_NO NEW_CARD_NO RNK1 RNK2
---------- ---------------- ---------------- ---------- ----------
555 444444 1231263 1 5
555 333333 1231263 1 4
555 222222 1231263 1 3
555 111111 1231263 1 2
555 000000 1231263 1 1
555 555555 1231263 1 6
555 666666 1231263 1 7
555 000000 1234566 2 1
555 111111 1234566 2 2
555 222222 1234566 2 3
555 333333 1234566 2 4
...
666 222222 4564566 3 3
666 333333 4564566 3 4
40 rows selected
...具有相同日期的生成40行,因为每个新卡号基于前缀计算映射到每个旧卡号;但是分析列具有唯一的组合,因此您可以进行过滤,而不是查找匹配的结果:
select prefix, card_no, new_card_no
from (
select cnm.prefix, cnm.card_no, c.card_no as new_card_no,
dense_rank() over (partition by cnm.prefix order by c.card_no) rnk1,
dense_rank() over (partition by c.card_no order by cnm.prefix, cnm.card_no) rnk2
from card_no_map cnm
join cards c
on case when c.card_no like '123%' then 555
when c.card_no like '456%' then 666
else -1 end = cnm.prefix
where cnm.new_card_no is null
)
where rnk1 = rnk2;
PREFIX CARD_NO NEW_CARD_NO
---------- ---------------- ----------------
555 000000 1231263
555 111111 1234566
555 222222 1236547
555 333333 1236549
666 000000 4560001
666 111111 4561234
666 222222 4564566
7 rows selected
......看起来更有前途。然后可以将其用作合并中的using
子句:
merge into card_no_map cnm
using (
select prefix, card_no, new_card_no
from (
select cnm.prefix, cnm.card_no, c.card_no as new_card_no,
dense_rank() over (partition by cnm.prefix order by c.card_no) rnk1,
dense_rank() over (partition by c.card_no order by cnm.prefix, cnm.card_no) rnk2
from card_no_map cnm
join cards c
on case when c.card_no like '123%' then 555
when c.card_no like '456%' then 666
else -1 end = cnm.prefix
where cnm.new_card_no is null
)
where rnk1 = rnk2
) tmp
on (tmp.prefix = cnm.prefix and tmp.card_no = cnm.card_no)
when matched then update set cnm.new_card_no = tmp.new_card_no;
7 rows merged.
select * from card_no_map;
PREFIX CARD_NO NEW_CARD_NO
---------- ---------------- ----------------
555 000000 1231263
555 111111 1234566
555 222222 1236547
555 333333 1236549
555 444444
555 555555
555 666666
666 000000 4560001
666 111111 4561234
666 222222 4564566
666 333333
或者您可以使用相同的子查询进行直接更新:
update card_no_map cnm
set new_card_no = (
select new_card_no
from (
select cnm.prefix, cnm.card_no, c.card_no as new_card_no,
dense_rank() over (partition by cnm.prefix order by c.card_no) rnk1,
dense_rank() over (partition by c.card_no order by cnm.prefix, cnm.card_no) rnk2
from card_no_map cnm
join cards c
on case when c.card_no like '123%' then 555
when c.card_no like '456%' then 666
else -1 end = cnm.prefix
where cnm.new_card_no is null
) t
where t.rnk1 = t.rnk2
and t.prefix = cnm.prefix
and t.card_no = cnm.card_no
)
where cnm.new_card_no is null;
类似的分析方法正在用于我的另一个答案,但结果代码(合并或更新)可以说有点简单,因为它没有CTE;但是它可能会使用更多资源,因为第一个中间结果集可能很大。
答案 1 :(得分:0)
将cards
中的唯一值分配给card_no_map
中的每个空行会使相关更新有点混乱。您无法更新或合并到视图中,但可以使相关性在行之间匹配。
您可以根据其前缀:
为每个地图指定名义行号select rowid as rid,
prefix,
row_number() over (partition by prefix order by rowid) as rn
from card_no_map
where new_card_no is null
您可以根据匹配的前缀为每张卡分配一个名义行号:
select card_no,
case when card_no like '123%' then 555
when card_no like '456%' then 666
else -1 end as prefix,
row_number() over (partition by case when card_no like '123%' then 555
when card_no like '456%' then 666
else -1 end order by card_no) as rn
from cards
然后,您可以在更新子查询中将这两个查询用作CTE(或者如果您愿意,可以使用内联视图),将它们连接到前缀和名义行号,然后将结果与通过其rowid更新的行相关联:
update card_no_map cnm
set cnm.new_card_no = (
with t1 as (
select rowid as rid,
prefix,
row_number() over (partition by prefix order by card_no) as rn
from card_no_map
where new_card_no is null
),
t2 as (
select card_no,
case when card_no like '123%' then 555
when card_no like '456%' then 666
else -1 end as prefix,
row_number() over (partition by case when card_no like '123%' then 555
when card_no like '456%' then 666
else -1 end order by card_no) as rn
from cards
)
select t2.card_no
from t1 join t2 on t2.prefix = t1.prefix and t2.rn = t1.rn
where t1.rid = cnm.rowid
)
where cnm.new_card_no is null;
使用示例数据添加到最终的问题:
select * from card_no_map;
PREFIX CARD_NO NEW_CARD_NO
---------- ---------------- ----------------
555 000000 1231263
555 111111 1234566
555 222222 1236547
555 333333 1236549
555 444444
555 555555
555 666666
666 000000 4560001
666 111111 4561234
666 222222 4564566
666 333333
分配卡号的顺序与您的样本输出不符,但我只是基于rowid
的排序;如果您有更好的方式来订购它们,请更改row_number()
以执行此操作。
我觉得有一种更简单的方法可以做到这一点但是现在却让我不知所措......不得不再次点击地图表似乎没有效率。