Sql 以列而不是行的形式从表中获取分组数据

Sql 以列而不是行的形式从表中获取分组数据,sql,oracle,Sql,Oracle,我有一个具有以下模式的表:(日期、名称、状态),其中状态可以是“正在处理”、“活动”和“关闭”。参赛作品样本如下: |------------+---------+------------| | Date | Name | Status | |------------+---------+------------| | 2011-07-01 | Alice | Processing | | 2011-07-01 | Alice | Active | |

我有一个具有以下模式的表:(日期、名称、状态),其中状态可以是“正在处理”、“活动”和“关闭”。参赛作品样本如下:

|------------+---------+------------|
|       Date | Name    | Status     |
|------------+---------+------------|
| 2011-07-01 | Alice   | Processing |
| 2011-07-01 | Alice   | Active     |
| 2011-07-02 | Alice   | Closed     |
| 2011-07-01 | Bob     | Active     |
| 2011-07-02 | Charlie | Processing |
|------------+---------+------------|
我使用以下查询获取不同状态下的帐户数:

select date, status, count(distinct name)
from accounts
group by date, status
它给出了以下内容:

2011-07-01 Processing 1
2011-07-01 Active 2
2011-07-02 Active 1
2011-07-02 Closed 1
如何获取列中的数据?i、 e

2011-07-01 2 1 0
2011-07-02 1 0 1

其中第一列是日期,第二列是处于活动状态的帐户数,第三列是处于处理状态的帐户数,最后一列是处于关闭状态的帐户数?我唯一能想到的是为每个状态编写三个子查询,并执行父查询来选择每个状态。但它似乎不太可扩展(例如,如果我必须添加一个新状态,我必须修改父查询并添加一个子查询)。

确切的语法将取决于您的数据库引擎,但在PostgreSQL和其他可能的数据库引擎中,这将起作用。这可能会在Oracle中一字不差地工作,因为Postgres往往会大量复制Oracle语法

SELECT
    date,
    SUM((Status='Processing')::INT) AS Processing,
    SUM((Status='Active')::INT) AS Active,
    SUM((Status='Closed')::INT) AS Closed
FROM accounts
GROUP BY date;

您也可以在oracle中使用内置透视功能

SELECT * FROM accounts 
pivot ( count(distinct name) for status in ('Active','Processing','Closed')); 
此功能由在oracle数据库方面有丰富经验的人员推荐。。这就是我粘贴到这里的原因:-)

这是(在Oracle 11g之前)进行透视的标准方法:

SQL> create table mytable (mydate,name,status)
  2  as
  3  select date '2011-07-01', 'Alice', 'Processing' from dual union all
  4  select date '2011-07-01', 'Alice', 'Active' from dual union all
  5  select date '2011-07-02', 'Alice', 'Closed' from dual union all
  6  select date '2011-07-01', 'Bob', 'Active' from dual union all
  7  select date '2011-07-02', 'Charlie', 'Processing' from dual
  8  /

Table created.

SQL> select mydate
  2       , count(case status when 'Active' then 1 end)     a
  3       , count(case status when 'Processing' then 1 end) p
  4       , count(case status when 'Closed' then 1 end)     c
  5    from mytable
  6   group by mydate
  7   order by mydate
  8  /

MYDATE                       A          P          C
------------------- ---------- ---------- ----------
01-07-2011 00:00:00          2          1          0
02-07-2011 00:00:00          0          1          1

2 rows selected.
问候,

Rob.

您正在使用哪个数据库?Oracle目前(不确定是哪个版本)。这不包括不同的名称状态,对吗?对。如果这是要求,原始海报需要您的查询。这张海报包含语法错误,“date”永远不能是真实的列,但如果某个名称在某一天多次具有相同的状态,则此查询就是其中之一。@Rob:好的,我知道了,这是表别名中的
AS
。Oracle不喜欢这样。演员是否也使用了
::INT
Oracle语法?
SELECT date
   , SUM(CASE status WHEN 'Active'     THEN cnt ELSE 0 END) AS a
   , SUM(CASE status WHEN 'Processing' THEN cnt ELSE 0 END) AS p
   , SUM(CASE status WHEN 'Closed'     THEN cnt ELSE 0 END) AS c
FROM 
  ( SELECT date, status, COUNT(DISTINCT name) AS cnt
    FROM accounts
    GROUP BY date, status
  ) grp
GROUP BY date
ORDER BY date