问题的SQL顺序 - 续

时间:2009-04-30 06:18:44

标签: sql plsql

此问题是我earlier query的延续。它仍然无法正常工作。 它是关于ORDER BY子句的。我正在尝试使用名为“sortby”的变量进行排序。

此处,现在使用DECODE()函数选择ORDER BY子句作为单独的列(,如@devio在此问题的原始版本中的回答中所建议的那样)。

在这种情况下,让我们说sortby ='memberCount',我把它作为decode()中的第一个参数传递给我; memberCount 是grptest表中的COLUMN。

select distinct gl.group_id,
       decode('memberCount', 'name',        gl.group_name_key,
                             'description', gl.group_description_key,
                             'memberCount', gl.member_count)
             as p_sortby,
       gl.group_name,
       gl.group_description,
       gl.status_code,
       gl.member_count,
       (select grpp.group_name
           from grptest_relationship grel join grptest grpp
                   on grel.parent_group_id = grpp.group_id
           where grel.child_group_id = gl.group_id) as parent_group_name,
       gl.group_name_key,
       gl.group_description_key
   from grptest gl
   where gl.group_org_id = '3909'
     and (gl.group_name_key like '%' || 'GROUP' || '%')
order by 2;

它不起作用。

但是如果我在上面的解码中将'name'作为第一个参数传递,它就可以了。 这是我原来的问题,为什么它不适用于memberCount。

2 个答案:

答案 0 :(得分:2)

我评论道:

  

你得到的错误是什么?或者你得到的错误行为是什么?在我的问题适应我的数据库时,我必须确保在DECODE()可接受之前将数字列转换为字符类型 - 其他两列是字符列。完成后,以及在“79”之后和“80”之前按字母顺序排序数字的次要问题,我得到了一个合适的结果。

罗希特问:

  

感谢您的投入。我想我对你提到的那个小问题感到困惑,“在'79'之后和'80'之前按字母顺序排序数字'8'。”我不知道这里有什么东西?另外,您可以帮我查询“在DECODE()可接受之前如何确保将数字列转换为字符类型”。你可以在这方面修改我上面的查询吗?


我使用的表是'元素表':

-- Tables for storing information about chemical elements and chemical compounds
-- See: http://www.webelements.com/ for elements.
-- See: http://ie.lbl.gov/education/isotopes.htm for isotopes.

CREATE TABLE elements
(
    atomic_number   INTEGER NOT NULL UNIQUE
                    CHECK (atomic_number > 0 AND atomic_number < 120),
    symbol          CHAR(3) NOT NULL UNIQUE,
    name            CHAR(20) NOT NULL UNIQUE,
    atomic_weight   DECIMAL(8,4) NOT NULL,
    stable          CHAR(1) DEFAULT 'Y' NOT NULL
                    CHECK (stable IN ('Y', 'N'))
);

这是一个有趣的表,因为它有三个真正的候选键(原子序数,名称和符号各自唯一),并且根据上下文(同位素与化学品),最好使用原子序数或符号作为连接键。

我使用的查询是:

select decode('atomic_number',
                    'name',          name,
                    'symbol',        symbol,
                    'atomic_number', atomic_number||''),
        name, symbol, atomic_number
    from elements
    order by 1;

select decode('name',
                    'name',          name,
                    'symbol',        symbol,
                    'atomic_number', atomic_number||''),
        name, symbol, atomic_number
    from elements
    order by 1;

select decode('symbol',
                    'name',          name,
                    'symbol',        symbol,
                    'atomic_number', atomic_number||''),
        name, symbol, atomic_number
    from elements
    order by 1;

这些证明了三个排序 - 按符号,按名称和原子序数。

原子序数排序的部分结果集是:

77      Iridium         Ir      77
78      Platinum        Pt      78
79      Gold            Au      79
8       Oxygen          O       8
80      Mercury         Hg      80
81      Thallium        Tl      81

因为原子序数被强制转换为字符串,所以排序按字符串顺序排列,当被视为字符串时,'8'出现在'79'之后和'80'之前,如图所示。避免这个问题的一种方法是:

select decode('atomic_number',
                    'name',          name,
                    'symbol',        symbol,
                    'atomic_number', lpad(atomic_number, 3)),
        name, symbol, atomic_number
    from elements
    order by 1;

生成以下内容(虽然不明显,但在第一列的开头有一个额外的空白):

 77     Iridium         Ir      77
 78     Platinum        Pt      78
 79     Gold            Au      79
 80     Mercury         Hg      80
 81     Thallium        Tl      81
 82     Lead            Pb      82

这使用空间在(ASCII,Latin-1,Unicode)排序序列中任何数字之前的知识,并且原子序数不超过3位。或者,我可以使用“LPAD(atomic_number, 3, '0')”来填充数据。我在Solaris 10上使用IBM Informix Dynamic Server(IDS)11.50.FC3W2进行了测试.IDS非常容忍类型不匹配,并自动将atomic_number参数转换为LPAD为字符串。其他DBMS可能不那么宽容;你必须明确地施放价值。

回到问题......

假设memberCount是一个数字列且值不超过4位数(如果它们更长则适当调整),可以写入查询:

select distinct gl.group_id,
       decode('memberCount', 'name',        gl.group_name_key,
                             'description', gl.group_description_key,
                             'memberCount', LPAD(gl.member_count, 4))
             as p_sortby,
       gl.group_name,
       gl.group_description,
       gl.status_code,
       gl.member_count,
       (select grpp.group_name
           from grptest_relationship grel join grptest grpp
                   on grel.parent_group_id = grpp.group_id
           where grel.child_group_id = gl.group_id) as parent_group_name,
       gl.group_name_key,
       gl.group_description_key
   from grptest gl
   where gl.group_org_id = '3909'
     and (gl.group_name_key like '%' || 'GROUP' || '%')
order by 2;

或者您可能需要:

LPAD(CAST(memberCount AS CHAR(4)), 4)

或其他一些略微DBMS特定的咒语,可以达到同样的效果。

由于您没有为查询提供架构(更少的示例数据),因此我的数据库中没有您的表,因此我无法演示您的查询工作

答案 1 :(得分:0)

我知道

order by p_sortby

不会工作,但你可以试试

order by decode('memberCount', 
  'name', gl.group_name_key,
  'description', gl.group_description_key, 
  'memberCount', gl.member_count)

编辑:

我记得另一种方式:

select * from (
  select column1, decode(....) as column2, .... from table1
) t1
order by 2

这种方式甚至可能更快