查看: 397|回复: 2

[每日一题] PL/SQL Challenge 每日一题:2020-12-1 函数

[复制链接]
论坛徽章:
523
奥运会纪念徽章:垒球
日期:2008-09-15 01:28:12生肖徽章2007版:鸡
日期:2008-11-17 23:40:58生肖徽章2007版:马
日期:2008-11-18 05:09:48数据库板块每日发贴之星
日期:2008-11-29 01:01:02数据库板块每日发贴之星
日期:2008-12-05 01:01:03生肖徽章2007版:虎
日期:2008-12-10 07:47:462009新春纪念徽章
日期:2009-01-04 14:52:28数据库板块每日发贴之星
日期:2009-02-08 01:01:03生肖徽章2007版:蛇
日期:2009-03-09 22:18:532009日食纪念
日期:2009-07-22 09:30:00
发表于 2021-1-11 22:13 | 显示全部楼层 |阅读模式

最先答对且答案未经编辑的puber将获得纪念章一枚(答案不可编辑但可发新贴补充或纠正),其他会员如果提供有价值的分析、讨论也可获得纪念章一枚。

每两周的优胜者可获得itpub奖励的技术图书一本。

以往旧题索引:
http://www.itpub.net/forum.php?m ... eid&typeid=1808

原始出处:
https://devgym.oracle.com/

作者:Kim Berg Hansen

运行环境:SQLPLUS, SERVEROUTPUT已打开, 最低版本要求:11.2
注:本题给出答案时候要求给予简要说明才能得到奖品

我有一张表保存着服装以及它们的尺码:
create table qz_products (
   id       integer primary key
, name     varchar2(20)
, sizing   varchar2(1)
);

insert into qz_products values (142, 'Black cotton hoodie', 'L');
insert into qz_products values (149, 'Olive green T-shirt', 'S');
insert into qz_products values (157, 'Dark blue jeans'    , 'M');

commit;

不幸的是,原来的数据是以丹麦文输入的,而 S, M 和 L的意义如下:

S 在丹麦文中是 "Stor" 表示大号
M 在丹麦文中是 "Middel" 表示中号
L 在丹麦文中是 "Lille" 表示小号

但是,现在每个人都使用国际上基于英文的值,即使在丹麦也是如此,所以我想要把SIZING的值进行修改,所有的L修改成S, 所有的S修改成L。

每个选项包含了一个或多个UPDATE语句来达到此目的。哪些选项可以执行不出错,按需求修改了表,使得 选项执行之后,这个测试查询返回所示的输出:

select id, name, sizing
from qz_products
order by id;

        ID NAME                 S
---------- -------------------- -
       142 Black cotton hoodie  S
       149 Olive green T-shirt  L
       157 Dark blue jeans      M

(A)
update qz_products
set sizing = 'X'
where sizing = 'S';

update qz_products
set sizing = 'S'
where sizing = 'L';

update qz_products
set sizing = 'L'
where sizing = 'X';

(B)
update qz_products
set sizing = 'L'
where sizing = 'S';

update qz_products
set sizing = 'S'
where sizing = 'L';

(C)
update qz_products
set sizing = translate(sizing, 'LMS', 'SML');

(D)
update qz_products
set sizing = translate(sizing, 'LS', 'SL');

(E)
update qz_products
set sizing = case sizing
                when 'L' then 'S'
                when 'M' then 'M'
                when 'S' then 'L'
             end;

(F)
update qz_products
set sizing = case sizing
                when 'L' then 'S'
                when 'S' then 'L'
             end;

(G)
update qz_products
set sizing = case sizing
                when 'L' then 'S'
                when 'S' then 'L'
                else sizing
             end;            

(H)
update qz_products
set sizing = case sizing
                when 'L' then 'S'
                when 'S' then 'L'
             end
where sizing in ('L', 'S');
论坛徽章:
18
山治
日期:2017-01-11 16:13:26妮可·罗宾
日期:2020-09-01 08:52:07秀才
日期:2018-01-02 10:32:00技术图书徽章
日期:2017-08-23 14:17:00技术图书徽章
日期:2017-08-23 14:17:00秀才
日期:2017-08-11 15:30:05秀才
日期:2017-08-11 15:30:05秀才
日期:2017-08-11 15:30:05秀才
日期:2017-08-11 15:30:05秀才
日期:2017-08-11 15:30:05
发表于 2021-1-13 09:55 | 显示全部楼层
答案 ACDEGH

A)  正确,通过一个'X'值做中间,来替换'S'和'L'

B) 错误,第二个update语句更新了两行,所以有2个'S',而没有'L'

C) 正确,通过translate函数实现,这个解题思路很巧妙

D)  正确,同C,使用translate函数,只是去掉了一个不用替换的'M'

E)  正确,update结合case语句使用,这是最开始想到的方法

F)  错误,case语句没有else,则默认为else null,'M'被替换成null

G)  正确,修复了F的问题,增加esle,默认为表原有的值,无需替换

H)  正确,修复了F的问题,where子句,增加了限定  

使用道具 举报

回复
论坛徽章:
523
奥运会纪念徽章:垒球
日期:2008-09-15 01:28:12生肖徽章2007版:鸡
日期:2008-11-17 23:40:58生肖徽章2007版:马
日期:2008-11-18 05:09:48数据库板块每日发贴之星
日期:2008-11-29 01:01:02数据库板块每日发贴之星
日期:2008-12-05 01:01:03生肖徽章2007版:虎
日期:2008-12-10 07:47:462009新春纪念徽章
日期:2009-01-04 14:52:28数据库板块每日发贴之星
日期:2009-02-08 01:01:03生肖徽章2007版:蛇
日期:2009-03-09 22:18:532009日食纪念
日期:2009-07-22 09:30:00
 楼主| 发表于 2021-1-14 22:33 | 显示全部楼层
答案ACDEGH, 2楼得奖。

A:
首先,我们更新S到一个未使用的尺码值X,然后更新L到S,最后X到L。这样做是可行的(只要数据中没有X作为尺码的行),但有3条更新语句,工作量很大。

B:
跳过临时更新到X的语句是行不通的,因为我们在第一条语句中更新的那些行也会在第二条语句中更新,导致这个错误的输出:

        ID NAME                 S
---------- -------------------- -
       142 Black cotton hoodie  S
       149 Olive green T-shirt  S
       157 Dark blue jeans      M
            
C:
在一次更新中完成是更容易和更安全的,例如使用TRANSLATE函数将一个集合中的单个字符翻译成其他字符。这里我们把所有的L翻译成S,把M翻译成M(不是必须的,但不影响正确性),把S翻译成L,这样就得到了想要的结果。

D:
正如前一选项所指出的,我们不需要将M翻译成M,所以在这里我们跳过它,它的效果很好。有M的行只是没有变化,更新为原来的值。

E:
我们也可以用CASE来代替翻译字符,从一个完整的字符串到另一个完整的字符串进行显式映射。这很好用,只要表中除了S、M和L之外没有其他大小值。

F:
使用TRANSLATE,我们可以简化C选项,并在D选项中省略M到M的转换,但是当我们试图通过省略CASE结构中的M到M映射来简化前一选项时,我们最终会将所有非S或L的值(在这种情况下,所有M尺码)更新为NULL,导致错误的输出:

        ID NAME                 S
---------- -------------------- -
       142 Black cotton hoodie  S
       149 Olive green T-shirt  L
       157 Dark blue jeans

G:
我们可以通过添加一个ELSE子句来修正一选项,确保如果它不是L或S,我们就保留原来的值。

H:
但更好的解决方法是加入一个WHERE子句,确保我们只更新那些需要更新的记录。这样我们就知道两个WHEN子句涵盖了所有的可能性,我们就不需要担心ELSE子句了。

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 
京ICP备09055130号-4  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表