Oracle具有长解码/案例功能

时间:2010-10-05 10:40:38

标签: sql oracle plsql

我有另一个简单的。如何在oracle中的函数内进行长解码?

我的选择如下:

select something, sum(ofsomethingelse)
from a_table
where code in 
('390','391','392','393','394','395','396','397','398','400','402','406',
'407','408','409','410','411','412','413','414','416','418','471','473',
'1734','1742','1735','1736','1737','1738','1739','1740','1741','1745',
'1748','1752','1760','1753','1754','1755','1756','1757','1758','1759',
'1763','1766','1902','1904','1003','1011','1004','1005','106','1007',
'1008','1009','1010','1159','1161','1015','1023','1016','1017','1018',
'1019','1020','1021','1022','1164','1166','1189','1191','1201','1209',
'1202','1203','1204','205','1206','1207','1208','1356','1358','1213',
'1221','1214','1215','1216','1217','1218','1219','1220','1361','1363',
'1386','1388','1401','1409','1402','1403','1404','1405','1406','1407',
'1408','1557','1559','1413','1421','1414','1415','1416','1417','1418',
'1419','1420','1562','1564','1587','1589','9033','9034','9035','9036',
'9037','9038','909','9040','9049','9050','9051','9052')
group by something
order by 1

我还有一些像我想要变成一个简洁查询的大型代码列表。

类似的东西:

CREATE OR REPLACE FUNCTION grouping_func (id_in IN varchar2)
RETURN varchar2
AS
res varchar(255);
BEGIN
   res := CASE id_in
            WHEN id_in in ([long list of ids from query1]) THEN 'Group1'
            WHEN id_in in ([long list of ids from query2]) THEN 'Group2'
            WHEN id_in in ([long list of ids from query3]) THEN 'Group3'
            ELSE id_in
          END;
    RETURN res;
END;

所以我可以有一个清晰的查询,只是将这个函数用于我所喜欢的组和所有方式:)

问题是我在切换案例中无法使用id_in in ([long list of ids from query3])而且我在plsql中非常使用n00b ...

我可以获得优雅方法的建议吗?

谢谢!

F。

3 个答案:

答案 0 :(得分:2)

这是一个可能的解决方案:创建2个表:

create table GROUPS 
(
GRP_ID INTEGER,
GRP_NAME VARCHAR2(20) // name of the group
);

create table LONGLIST
(
LL_ID INTEGER,
LL_NAME  VARCHAR2(20) // item of your big list
GRP_ID INTEGER // (foreign key)
);

这样你只需要加入表,不需要CASE或DECODE

最终查询看起来像这样:

select g.grp_name, sum(ofsomethingelse)
from a_table a
inner join longlist ll on ll.ll_name = a.code
inner join groups g on g.grp_id = ll.grp_id
group by g.grp_name

答案 1 :(得分:1)

实际上,第一次尝试的唯一问题是你混淆了CASE表达式的两种语法。

如果您使用表达式(例如id_in)跟随CASE关键字,那么您正在切换该表达式的值,并且每个WHEN子句必须包含将被检查的单个表达式与第一个表达式平等。

或者,您可以在CASE之后立即跳过表达式,并在每个WHEN子句中指定完整的布尔条件。

所以,其中任何一个都适合你:

   res := CASE id_in
         WHEN 390 THEN 'Group1'
         WHEN 391 THEN 'Group1'
         WHEN 392 THEN 'Group2'
         ...etc...

   res := CASE
            WHEN id_in in ([long list of ids from query1]) THEN 'Group1'
            WHEN id_in in ([long list of ids from query2]) THEN 'Group2'
            WHEN id_in in ([long list of ids from query3]) THEN 'Group3'
            ELSE id_in
          END;

请注意,总的来说,我同意其他人的看法,最好的方法是将ID值映射到另一个表中的组,并将查询更改为连接。

答案 2 :(得分:0)

请确保您的长ID列表不相交。

CREATE OR REPLACE FUNCTION grouping_func(id_in IN varchar2) RETURN varchar2 AS
  res varchar2(255);
BEGIN
  select gr
    into retval
    from (select 'Group1' gr
            from dual
           where id_in in ('[long list of ids from query1]')
          union all
          select 'Group2' gr
            from dual
           where id_in in ('[long list of ids from query2]')
          union all
          select 'Group3' gr
            from dual
           where id_in in ('[long list of ids from query3]'));

  exception 
    when no_data_found then
     return null;
    when too_many_rows then
     return null;    
END;

我猜这不是最亮的东西,但会对你的功能起作用。并且,是的,最好将这些代码存储在您可以加入查询的单独表中。