使用别名对列进行分组

时间:2014-03-27 00:03:14

标签: sql oracle

好吧,我有一个非常简单的查询 - 三列,第一列我希望按第二列分组,第三列只是一个计数。第一列ID有十几个值。第二,CODE有六个。如果我做一个简单的选择

SELECT ID,CODE,THINGIMCOUNTING FROM TABLE GROUP BY ID

我想要的是将列作为ID列的别名,以便CODE列不重复,因为多个ID可以引用相同的CODE,我不能通过没有重复 - 只想稍微清理一下。

我的第一个想法是别名,但这似乎不是Oracle SQL中的一个选项 - 例如

SELECT ID as FIRST_ID, ID as SECOND_ID, ID as THIRD_ID, CODE, THINGIMCOUNTING<BR> WHERE FIRST_ID = "1" AND SECOND_ID="2" AND THIRD_ID="3" GROUP BY CODE

或其他相似之处。然后我读到了INTERSECT关键字,但是当我使用它时,我得不到任何结果 - 只是列。类似

SELECT IDELECT ID,CODE,THINGIMCOUNTING FROM TABLE<BR>WHERE ID = "1" GROUP BY CODE {
{1}}
INTERSECT

我试图单独从查询中获得一个类似矩阵的矩阵 - 我是否过于复杂?有没有一个简单,优雅的解决方案,我没有看到?谢谢!

2 个答案:

答案 0 :(得分:1)

使用Pivot子句

非常简单
Select * 
from
(   Select  id, 
            code, 
            THINGIMCOUNTING
     from table1)
Pivot 
  ( count(THINGIMCOUNTING) for id in (1 as id1 ,
                                      2 as id2 ,
                                      3 as id3))

Demo

另一种方法是使用SUM / CASE

Select 
    code,
    SUM(CASE WHEN id = 1 then 1 ELSE 0 END) id1,
    SUM(CASE WHEN id = 2 then 1 ELSE 0 END) id2,
    SUM(CASE WHEN id = 3 then 1 ELSE 0 END) id3
FROM
    table1
GROUP BY
  Code

DEMO

答案 1 :(得分:0)

<强>更新

这个查询真的属于答案的底部,因为我最初没有提出它。但要切入追逐......这样的事情可能会返回您指定的结果集。

SELECT MIN(CASE WHEN i.rn = 1 THEN i.id END) AS id1
     , MIN(CASE WHEN i.rn = 2 THEN i.id END) AS id2
     , MIN(CASE WHEN i.rn = 3 THEN i.id END) AS id3
     , MIN(CASE WHEN i.rn = 4 THEN i.id END) AS id4
     , s.CODE
     , s.cnt_
  FROM ( SELECT t.CODE
              , COUNT(1) AS cnt_
           FROM mytable t
          GROUP BY t.CODE
       ) s
  LEFT
  JOIN ( SELECT ROW_NUMBER() OVER (PARTITION BY j.CODE ORDER BY j.ID ASC) rn
              , j.CODE
              , j.ID
           FROM mytable j
       ) i
    ON i.CODE = s.CODE
 GROUP BY s.CODE, s.cnt_

(我不得不深入研究Oracle文档,找到可以按组分配行号的分析函数的语法。)


<强> ORIGINAL

我不确定您要查找的结果集。听起来你想要CODE的DISTINCT值,并希望通过不同的代码值得到counts

这部分很容易,对:

 SELECT t.CODE
      , COUNT(1)
   FROM mytable t
  GROUP BY t.CODE

返回

code count
---- -----
fee      4
fi       2
fo       3   

如果这是您要查找的行数,以及您想要返回的count值,那么在同一行上获取与该代码对应的ID值会有点问题。

假设,

SELECT t.CODE
     , t.ID
  FROM mytable t
 ORDER BY t.CODE, t.ID

返回:

code id
---- --
fee   2
fee   3
fee   5
fee   7
fi   11
fi   13
fo    4
fo    6
fo    8

这样,这个查询可以获取您希望为每个代码返回的ID值的“列表”,但这些ID值位于不同的行上,您希望在结果集中表示这个值,如下所示:

id1 id2 id3 id4 code count
--- --- --- --- ---- -----
  2   3   5   7  fee     4
 11  13          fi      2
  4   6   8      fo      3

这有点问题。首先,必须在语句中指定列数,在语句运行时不能动态更改。因此,需要有一个可以返回的id值的上限。

但是,完全不清楚你真正想要的结果集。一个例子可以用很长的路来解释你想要达到的结果。

可能有一个分析函数可以轻松地执行此类型的数据透视,但使用普通的旧ANSI SQL获取此结果可能会成为一些可怕的SQL文本。

我建议查看分析函数。

正如我所看到的那样,“技巧”将在每个代码中为id值分配“行号”。

如果你可以得到一个看起来像这样的结果集,每个代码值中都有一个递增的行号:

code rn id
---- -- --
fee   1  2
fee   2  3
fee   3  5
fee   4  7
fi    1 11
fi    2 13
fo    1  4
fo    2  6 
fo    3  8

然后你就可以这样了。可以使用rn rownumber生成结果集的查询(无论是什么)将作为内联视图插入到此查询中,在此处显示为i

SELECT MIN(CASE WHEN i.rn = 1 THEN i.id END) AS id1
     , MIN(CASE WHEN i.rn = 2 THEN i.id END) AS id2
     , MIN(CASE WHEN i.rn = 3 THEN i.id END) AS id3
     , MIN(CASE WHEN i.rn = 4 THEN i.id END) AS id4
     , s.CODE
     , s.cnt_
  FROM ( SELECT t.CODE
              , COUNT(1) AS cnt_
           FROM mytable t
          GROUP BY t.CODE
       ) s
  LEFT
  JOIN ( 
         -- SELECT code, rn, id --
       ) i
    ON i.CODE = s.CODE
 GROUP BY s.CODE, s.cnt_

使用SELECT列表中的条件表达式返回id值,具体取决于rn的值。将rn = 1返回到第一列(在具有匹配CODE的行上),将rn = 2返回到第二列。 “技巧”实际上是在没有返回id值时,而不是'正确'的行号。我们必须将它们包含在某种聚合函数中,以便让外部查询上的GROUP BY起作用。

您可以使用分析/窗口类型函数为每个代码的每个id分配“行号”。好像我似乎有些语法(我知道这不对,我只是在捅它......)

我不确定是否可以在内联视图中使用它(我认为它可以在Oracle中使用),但我认为Oracle和SQL Server中的语法之间存在差异(以及支持的实际函数的差异) )。 MySQL完全没有这种类型的分析功能。


<强>更新

参考:http://docs.oracle.com/cd/E11882_01/server.112/e26088/functions156.htm#SQLRF06100

看起来获取行号列的语法实际上是:

SELECT ROW_NUMBER() OVER (PARTITION BY j.CODE ORDER BY j.ID ASC) rn
     , j.CODE
     , j.ID
  FROM mytable j

所以,像这样:

SELECT MIN(CASE WHEN i.rn = 1 THEN i.id END) AS id1
     , MIN(CASE WHEN i.rn = 2 THEN i.id END) AS id2
     , MIN(CASE WHEN i.rn = 3 THEN i.id END) AS id3
     , MIN(CASE WHEN i.rn = 4 THEN i.id END) AS id4
     , s.CODE
     , s.cnt_
  FROM ( SELECT t.CODE
              , COUNT(1) AS cnt_
           FROM mytable t
          GROUP BY t.CODE
       ) s
  LEFT
  JOIN ( SELECT ROW_NUMBER() OVER (PARTITION BY j.CODE ORDER BY j.ID ASC) rn
              , j.CODE
              , j.ID
           FROM mytable j
       ) i
    ON i.CODE = s.CODE
 GROUP BY s.CODE, s.cnt_