Oracle SQL: упрощение множественного выбора - PullRequest
1 голос
/ 06 декабря 2011

Мне нужно делать 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 ]

2 голосов
/ 06 декабря 2011

Попробуйте:

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

Включает довольно общий метод поворота результатов.Обратите внимание, что, поскольку нет ограничений на год, в результатах каждого месяца могут появляться данные за несколько лет - это также относится к исходному запросу.

2 голосов
/ 06 декабря 2011

Это операция поворота. В 11G:

образец

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
    )

отказ от ответственности: не проверено. Проверьте короткие названия месяцев на вашем языке.

1 голос
/ 06 декабря 2011

Создайте временную таблицу с необходимыми значениями (месяц и количество).

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

И последующие слова выберите то, что вам нужно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...