Oracle SQL:简化多个select语句

时间:2011-12-06 11:42:52

标签: sql oracle select

我需要在一年内每个月做一个COUNT,所以我这样做:

SELECT 
(
    SELECT  COUNT( {ENCOMENDA_LINHA}.[Quantidade])
    FROM (( {ENCOMENDA}
    INNER JOIN {ENCOMENDA_LINHA} ON ( {ENCOMENDA}.[Id] = {ENCOMENDA_LINHA}.[EncomendaId] ))
    INNER JOIN {PRODUTO} on ( {ENCOMENDA_LINHA}.[ProdutoId] = {PRODUTO}.[Id] ))
    WHERE {ENCOMENDA}.[EstadoId] = @EstadoEncomenda AND
    to_char({ENCOMENDA}.[DataSubmissao], 'MM') = '01' AND
    {PRODUTO}.[ProdutoTipoId] = @TipoProduto
) AS jan,
(
    SELECT  COUNT( {ENCOMENDA_LINHA}.[Quantidade])
    FROM (( {ENCOMENDA}
    INNER JOIN {ENCOMENDA_LINHA} ON ( {ENCOMENDA}.[Id] = {ENCOMENDA_LINHA}.[EncomendaId] ))
    INNER JOIN {PRODUTO} on ( {ENCOMENDA_LINHA}.[ProdutoId] = {PRODUTO}.[Id] ))
    WHERE {ENCOMENDA}.[EstadoId] = @EstadoEncomenda AND
    to_char({ENCOMENDA}.[DataSubmissao], 'MM') = '02' AND
    {PRODUTO}.[ProdutoTipoId] = @TipoProduto
) AS fev,
(
    SELECT  COUNT( {ENCOMENDA_LINHA}.[Quantidade])
    FROM (( {ENCOMENDA}
    INNER JOIN {ENCOMENDA_LINHA} ON ( {ENCOMENDA}.[Id] = {ENCOMENDA_LINHA}.[EncomendaId] ))
    INNER JOIN {PRODUTO} on ( {ENCOMENDA_LINHA}.[ProdutoId] = {PRODUTO}.[Id] ))
    WHERE {ENCOMENDA}.[EstadoId] = @EstadoEncomenda AND
    to_char({ENCOMENDA}.[DataSubmissao], 'MM') = '03' AND
    {PRODUTO}.[ProdutoTipoId] = @TipoProduto
) AS mar,
(
    SELECT  COUNT( {ENCOMENDA_LINHA}.[Quantidade])
    FROM (( {ENCOMENDA}
    INNER JOIN {ENCOMENDA_LINHA} ON ( {ENCOMENDA}.[Id] = {ENCOMENDA_LINHA}.[EncomendaId] ))
    INNER JOIN {PRODUTO} on ( {ENCOMENDA_LINHA}.[ProdutoId] = {PRODUTO}.[Id] ))
    WHERE {ENCOMENDA}.[EstadoId] = @EstadoEncomenda AND
    to_char({ENCOMENDA}.[DataSubmissao], 'MM') = '04' AND
    {PRODUTO}.[ProdutoTipoId] = @TipoProduto
) AS abr,
(
    SELECT  COUNT( {ENCOMENDA_LINHA}.[Quantidade])
    FROM (( {ENCOMENDA}
    INNER JOIN {ENCOMENDA_LINHA} ON ( {ENCOMENDA}.[Id] = {ENCOMENDA_LINHA}.[EncomendaId] ))
    INNER JOIN {PRODUTO} on ( {ENCOMENDA_LINHA}.[ProdutoId] = {PRODUTO}.[Id] ))
    WHERE {ENCOMENDA}.[EstadoId] = @EstadoEncomenda AND
    to_char({ENCOMENDA}.[DataSubmissao], 'MM') = '05' AND
    {PRODUTO}.[ProdutoTipoId] = @TipoProduto
) AS mai,
(
    SELECT  COUNT( {ENCOMENDA_LINHA}.[Quantidade])
    FROM (( {ENCOMENDA}
    INNER JOIN {ENCOMENDA_LINHA} ON ( {ENCOMENDA}.[Id] = {ENCOMENDA_LINHA}.[EncomendaId] ))
    INNER JOIN {PRODUTO} on ( {ENCOMENDA_LINHA}.[ProdutoId] = {PRODUTO}.[Id] ))
    WHERE {ENCOMENDA}.[EstadoId] = @EstadoEncomenda AND
    to_char({ENCOMENDA}.[DataSubmissao], 'MM') = '06' AND
    {PRODUTO}.[ProdutoTipoId] = @TipoProduto
) AS jun,
(
    SELECT  COUNT( {ENCOMENDA_LINHA}.[Quantidade])
    FROM (( {ENCOMENDA}
    INNER JOIN {ENCOMENDA_LINHA} ON ( {ENCOMENDA}.[Id] = {ENCOMENDA_LINHA}.[EncomendaId] ))
    INNER JOIN {PRODUTO} on ( {ENCOMENDA_LINHA}.[ProdutoId] = {PRODUTO}.[Id] ))
    WHERE {ENCOMENDA}.[EstadoId] = @EstadoEncomenda AND
    to_char({ENCOMENDA}.[DataSubmissao], 'MM') = '07' AND
    {PRODUTO}.[ProdutoTipoId] = @TipoProduto
) AS jul,
(
    SELECT  COUNT( {ENCOMENDA_LINHA}.[Quantidade])
    FROM (( {ENCOMENDA}
    INNER JOIN {ENCOMENDA_LINHA} ON ( {ENCOMENDA}.[Id] = {ENCOMENDA_LINHA}.[EncomendaId] ))
    INNER JOIN {PRODUTO} on ( {ENCOMENDA_LINHA}.[ProdutoId] = {PRODUTO}.[Id] ))
    WHERE {ENCOMENDA}.[EstadoId] = @EstadoEncomenda AND
    to_char({ENCOMENDA}.[DataSubmissao], 'MM') = '08' AND
    {PRODUTO}.[ProdutoTipoId] = @TipoProduto
) AS ago,
(
    SELECT  COUNT( {ENCOMENDA_LINHA}.[Quantidade])
    FROM (( {ENCOMENDA}
    INNER JOIN {ENCOMENDA_LINHA} ON ( {ENCOMENDA}.[Id] = {ENCOMENDA_LINHA}.[EncomendaId] ))
    INNER JOIN {PRODUTO} on ( {ENCOMENDA_LINHA}.[ProdutoId] = {PRODUTO}.[Id] ))
    WHERE {ENCOMENDA}.[EstadoId] = @EstadoEncomenda AND
    to_char({ENCOMENDA}.[DataSubmissao], 'MM') = '09' AND
    {PRODUTO}.[ProdutoTipoId] = @TipoProduto
) AS stb,
(
    SELECT  COUNT( {ENCOMENDA_LINHA}.[Quantidade])
    FROM (( {ENCOMENDA}
    INNER JOIN {ENCOMENDA_LINHA} ON ( {ENCOMENDA}.[Id] = {ENCOMENDA_LINHA}.[EncomendaId] ))
    INNER JOIN {PRODUTO} on ( {ENCOMENDA_LINHA}.[ProdutoId] = {PRODUTO}.[Id] ))
    WHERE {ENCOMENDA}.[EstadoId] = @EstadoEncomenda AND
    to_char({ENCOMENDA}.[DataSubmissao], 'MM') = '10' AND
    {PRODUTO}.[ProdutoTipoId] = @TipoProduto
) AS out,
(
    SELECT  COUNT( {ENCOMENDA_LINHA}.[Quantidade])
    FROM (( {ENCOMENDA}
    INNER JOIN {ENCOMENDA_LINHA} ON ( {ENCOMENDA}.[Id] = {ENCOMENDA_LINHA}.[EncomendaId] ))
    INNER JOIN {PRODUTO} on ( {ENCOMENDA_LINHA}.[ProdutoId] = {PRODUTO}.[Id] ))
    WHERE {ENCOMENDA}.[EstadoId] = @EstadoEncomenda AND
    to_char({ENCOMENDA}.[DataSubmissao], 'MM') = '11' AND
    {PRODUTO}.[ProdutoTipoId] = @TipoProduto
) AS nov,
(
    SELECT  COUNT( {ENCOMENDA_LINHA}.[Quantidade])
    FROM (( {ENCOMENDA}
    INNER JOIN {ENCOMENDA_LINHA} ON ( {ENCOMENDA}.[Id] = {ENCOMENDA_LINHA}.[EncomendaId] ))
    INNER JOIN {PRODUTO} on ( {ENCOMENDA_LINHA}.[ProdutoId] = {PRODUTO}.[Id] ))
    WHERE {ENCOMENDA}.[EstadoId] = @EstadoEncomenda AND
    to_char({ENCOMENDA}.[DataSubmissao], 'MM') = '12' AND
    {PRODUTO}.[ProdutoTipoId] = @TipoProduto
) AS dez

FROM dual

有没有办法简化这个? 干杯。

3 个答案:

答案 0 :(得分:2)

尝试:

SELECT COUNT(CASE WHEN to_char({ENCOMENDA}.[DataSubmissao], 'MM') = '01' 
                  THEN {ENCOMENDA_LINHA}.[Quantidade]) END) AS jan,
       COUNT(CASE WHEN to_char({ENCOMENDA}.[DataSubmissao], 'MM') = '02' 
                  THEN {ENCOMENDA_LINHA}.[Quantidade]) END) AS fev,
       COUNT(CASE WHEN to_char({ENCOMENDA}.[DataSubmissao], 'MM') = '03' 
                  THEN {ENCOMENDA_LINHA}.[Quantidade]) END) AS mar,
       COUNT(CASE WHEN to_char({ENCOMENDA}.[DataSubmissao], 'MM') = '04' 
                  THEN {ENCOMENDA_LINHA}.[Quantidade]) END) AS abr,
       COUNT(CASE WHEN to_char({ENCOMENDA}.[DataSubmissao], 'MM') = '05' 
                  THEN {ENCOMENDA_LINHA}.[Quantidade]) END) AS mai,
       COUNT(CASE WHEN to_char({ENCOMENDA}.[DataSubmissao], 'MM') = '06' 
                  THEN {ENCOMENDA_LINHA}.[Quantidade]) END) AS jun,
       COUNT(CASE WHEN to_char({ENCOMENDA}.[DataSubmissao], 'MM') = '07' 
                  THEN {ENCOMENDA_LINHA}.[Quantidade]) END) AS jul,
       COUNT(CASE WHEN to_char({ENCOMENDA}.[DataSubmissao], 'MM') = '08' 
                  THEN {ENCOMENDA_LINHA}.[Quantidade]) END) AS ago,
       COUNT(CASE WHEN to_char({ENCOMENDA}.[DataSubmissao], 'MM') = '09' 
                  THEN {ENCOMENDA_LINHA}.[Quantidade]) END) AS stb,
       COUNT(CASE WHEN to_char({ENCOMENDA}.[DataSubmissao], 'MM') = '10' 
                  THEN {ENCOMENDA_LINHA}.[Quantidade]) END) AS out,
       COUNT(CASE WHEN to_char({ENCOMENDA}.[DataSubmissao], 'MM') = '11' 
                  THEN {ENCOMENDA_LINHA}.[Quantidade]) END) AS nov,
       COUNT(CASE WHEN to_char({ENCOMENDA}.[DataSubmissao], 'MM') = '12' 
                  THEN {ENCOMENDA_LINHA}.[Quantidade]) END) AS dez
FROM (( {ENCOMENDA}
INNER JOIN {ENCOMENDA_LINHA} ON ( {ENCOMENDA}.[Id] = {ENCOMENDA_LINHA}.[EncomendaId] ))
INNER JOIN {PRODUTO} on ( {ENCOMENDA_LINHA}.[ProdutoId] = {PRODUTO}.[Id] ))
WHERE {ENCOMENDA}.[EstadoId] = @EstadoEncomenda AND
{PRODUTO}.[ProdutoTipoId] = @TipoProduto

包含一种旋转结果的相当通用的方法。请注意,由于年份没有限制,多年的数据可能会出现在每个月的结果中 - 原始查询也是如此。

答案 1 :(得分:2)

这是一个枢轴操作。在11G:

sample

SELECT *
  FROM (SELECT job, deptno, sum(sal) sal FROM emp GROUP BY job, deptno)
         PIVOT ( sum(sal) FOR deptno IN (10, 20, 30, 40) );

JOB               10         20         30         40
--------- ---------- ---------- ---------- ----------
CLERK           1300       1900        950
SALESMAN                              5600
PRESIDENT       5000
MANAGER         2450       2975       2850
ANALYST    

代码:

SELECT  * 
  FROM 
    ( SELECT 
      COUNT( {ENCOMENDA_LINHA}.[Quantidade])
    FROM (( {ENCOMENDA}
    INNER JOIN {ENCOMENDA_LINHA} 
       ON ( {ENCOMENDA}.[Id] = {ENCOMENDA_LINHA}.[EncomendaId] ))
    INNER JOIN {PRODUTO} 
       on ( {ENCOMENDA_LINHA}.[ProdutoId] = {PRODUTO}.[Id] ))
    WHERE 
      {ENCOMENDA}.[EstadoId] = @EstadoEncomenda AND
      {PRODUTO}.[ProdutoTipoId] = @TipoProduto
    PIVOT ( COUNT( {ENCOMENDA_LINHA}.[Quantidade]) 
            FOR to_char({ENCOMENDA}.[DataSubmissao], 'MON') IN
              ('JAN','FEB','MAR', ..., 'DEC')
    )

对于以前的版本,示例:

SELECT  *
  FROM  (SELECT job,
                sum(decode(deptno,10,sal)) DEPT10,
                sum(decode(deptno,20,sal)) DEPT20,
                sum(decode(deptno,30,sal)) DEPT30,
                sum(decode(deptno,40,sal)) DEPT40
           FROM scott.emp
       GROUP BY job)
ORDER BY 1;

代码:

SELECT  * 
  FROM 
    ( SELECT 
        COUNT( decode( to_char({ENCOMENDA}.[DataSubmissao], 'MON'), 
                       'JAN',
                       {ENCOMENDA_LINHA}.[Quantidade]
                      )
              ) JAN,
        COUNT( decode( to_char({ENCOMENDA}.[DataSubmissao], 'MON'), 
                       'FEB',
                       {ENCOMENDA_LINHA}.[Quantidade]
                      )
              ) FEB,
        ...
        COUNT( decode( to_char({ENCOMENDA}.[DataSubmissao], 'MON'), 
                       'DEC',
                       {ENCOMENDA_LINHA}.[Quantidade]
                      )
              ) DEC,
    FROM (( {ENCOMENDA}
    INNER JOIN {ENCOMENDA_LINHA} 
       ON ( {ENCOMENDA}.[Id] = {ENCOMENDA_LINHA}.[EncomendaId] ))
    INNER JOIN {PRODUTO} 
       on ( {ENCOMENDA_LINHA}.[ProdutoId] = {PRODUTO}.[Id] ))
    WHERE 
      {ENCOMENDA}.[EstadoId] = @EstadoEncomenda AND
      {PRODUTO}.[ProdutoTipoId] = @TipoProduto
    )
免责声明:未经测试。检查您所用语言的月份短名称。

答案 2 :(得分:1)

创建一个包含所需值(月份和数量)的临时表。

SELECT to_char({ENCOMENDA}.[DataSubmissao], 'MM'), COUNT( {ENCOMENDA_LINHA}.[Quantidade])
FROM (( {ENCOMENDA}
INNER JOIN {ENCOMENDA_LINHA} ON ( {ENCOMENDA}.[Id] = {ENCOMENDA_LINHA}.[EncomendaId] ))
INNER JOIN {PRODUTO} on ( {ENCOMENDA_LINHA}.[ProdutoId] = {PRODUTO}.[Id] ))
WHERE {ENCOMENDA}.[EstadoId] = @EstadoEncomenda AND
{PRODUTO}.[ProdutoTipoId] = @TipoProduto

然后选择你需要的东西。