AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / user-55557

BriteSponge's questions

Martin Hope
BriteSponge
Asked: 2016-04-23 02:38:18 +0800 CST

Lógica de avaliação CASE inesperada

  • 8

Sempre entendi que a CASEdeclaração funcionava com base no princípio de 'curto-circuito', pois a avaliação das etapas subsequentes não ocorre se uma etapa anterior for avaliada como verdadeira. (Esta resposta A instrução CASE do SQL Server avalia todas as condições ou sai na primeira condição TRUE? está relacionada, mas não parece cobrir esta situação e está relacionada ao SQL Server).

No exemplo a seguir, desejo calcular MAX(amount)entre um intervalo de meses que difere com base em quantos meses existem entre as datas de início e pagamento.

(Este é obviamente um exemplo construído, mas a lógica tem raciocínio de negócios válido no código real onde vejo o problema).

Se houver < 5 meses entre as datas de início e pagamento, a Expressão 1 será usada, caso contrário, a Expressão 2 será usada.

Isso resulta no erro "ORA-01428: argumento '-1' está fora do intervalo" porque 1 registro tem uma condição de dados inválido que resulta em um valor negativo para o início da cláusula BETWEEN do ORDER BY.

Consulta 1

SELECT ref_no,
       CASE WHEN MONTHS_BETWEEN(paid_date, start_date) < 5 THEN
-- Expression 1
          MAX(amount)
             OVER (PARTITION BY ref_no ORDER BY paid_date ASC 
             ROWS BETWEEN MONTHS_BETWEEN(paid_date, start_date) PRECEDING
             AND CURRENT ROW)
       ELSE
-- Expression 2
           MAX(amount)
             OVER (PARTITION BY ref_no ORDER BY paid_date ASC 
             ROWS BETWEEN 5 PRECEDING AND CURRENT ROW)
       END                
    END 
  FROM payment

Então, optei por esta segunda consulta para eliminar primeiro qualquer lugar que isso possa ocorrer:

SELECT ref_no,
       CASE WHEN MONTHS_BETWEEN(paid_date, start_date) < 0 THEN 0
       ELSE
          CASE WHEN MONTHS_BETWEEN(paid_date, start_date) < 5 THEN
             MAX(amount)
                OVER (PARTITION BY ref_no ORDER BY paid_date ASC 
                ROWS BETWEEN MONTHS_BETWEEN(paid_date, start_date) PRECEDING 
                AND CURRENT ROW)
          ELSE
             MAX(amount)
                OVER (PARTITION BY ref_no ORDER BY paid_date ASC 
                ROWS BETWEEN 5 PRECEDING AND CURRENT ROW)
          END                
       END
  FROM payment

Infelizmente, há algum comportamento inesperado que significa que os valores que a Expressão 1 usaria são validados, mesmo que a instrução não seja executada porque a condição negativa agora é capturada pelo CASE.

Posso contornar o problema usando ABSon the MONTHS_BETWEENem Expression 1 , mas acho que isso deve ser desnecessário.

Esse comportamento é o esperado? Em caso afirmativo, 'por que', pois parece ilógico para mim e mais como um bug?


Isso criará uma tabela e dados de teste. A consulta é simplesmente eu verificando se o caminho correto no CASEestá sendo seguido.

CREATE TABLE payment
(ref_no NUMBER,
 start_date DATE,
 paid_date  DATE,
 amount  NUMBER)
 
INSERT INTO payment
VALUES (1001,TO_DATE('01-11-2015','DD-MM-YYYY'),TO_DATE('01-01-2016','DD-MM-YYYY'),3000)

INSERT INTO payment
VALUES (1001,TO_DATE('01-11-2015','DD-MM-YYYY'),TO_DATE('12-12-2015','DD-MM-YYYY'),5000)

INSERT INTO payment
VALUES (1001,TO_DATE('10-03-2016','DD-MM-YYYY'),TO_DATE('10-02-2016','DD-MM-YYYY'),2000)

INSERT INTO payment
VALUES (1001,TO_DATE('01-11-2015','DD-MM-YYYY'),TO_DATE('03-03-2016','DD-MM-YYYY'),6000)

INSERT INTO payment
VALUES (1001,TO_DATE('01-11-2015','DD-MM-YYYY'),TO_DATE('28-11-2015','DD-MM-YYYY'),10000)

SELECT ref_no,
       CASE WHEN MONTHS_BETWEEN(paid_date, start_date) < 0 THEN '<0'
       ELSE
          CASE WHEN MONTHS_BETWEEN(paid_date, start_date) < 5 THEN
             '<5'
         --    MAX(amount)
         --       OVER (PARTITION BY ref_no ORDER BY paid_date ASC ROWS
         --       BETWEEN MONTHS_BETWEEN(paid_date, start_date) PRECEDING
         --       AND CURRENT ROW)
          ELSE
             '>=5'
         --    MAX(amount)
         --       OVER (PARTITION BY ref_no ORDER BY paid_date ASC ROWS
         --       BETWEEN 5 PRECEDING AND CURRENT ROW)
          END                
       END
  FROM payment
oracle
  • 3 respostas
  • 999 Views
Martin Hope
BriteSponge
Asked: 2015-10-07 02:58:37 +0800 CST

Quais valores IN-LIST não estão na tabela

  • 0

Estou procurando uma maneira simples de ver quais itens em minha IN-LIST não estão realmente na tabela. Parecia muito simples, mas acho que provavelmente estou pensando demais.

Tenho uma longa lista de códigos de itens fornecidos por um cliente e eles gostariam de atualizar um atributo na tabela para cada um desses códigos de itens. No entanto, preciso informar ao cliente se algum dos códigos que ele forneceu realmente não existe na tabela. Eu tentei fazer um COUNT (*) e um GROUP BY e tentei algumas variações usando MINUS, mas sempre se resume ao fato de que, se o valor não estiver no IN-LIST, não posso me referir a ele .

Exemplo: a tabela de itens tem 3 entradas

Item_code
12345
98765
65436

Lista de suprimentos do usuário de

12345
98765
65436
81764

Quero destacar ao cliente que o código '81764' não é um código de item válido. Posso fazer isso facilmente com PL/SQL, mas gostaria de uma solução SQL, se possível.

oracle
  • 1 respostas
  • 774 Views

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve