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 / dba / Perguntas / 342814
Accepted
user1708730
user1708730
Asked: 2024-10-05 22:09:39 +0800 CST2024-10-05 22:09:39 +0800 CST 2024-10-05 22:09:39 +0800 CST

Soma contínua com valor parcial do último dia

  • 772

Não consigo descobrir como escrever uma consulta que retorne uma soma contínua por item com base em regras de outra tabela.

Abaixo está uma tabela que lista em ordem cronológica o valor do estoque de um item em dias específicos.

Tabela 1: Estoque

item estoque data
Lâmina 10 03/01/2020
Lâmina 20 04/01/2020
Lâmina 30 05/01/2020
Lâmina 40 06/01/2020
Lâmina 50 07/01/2020
Lâmina 60 08/01/2020
Lâmina 70 09/01/2020
Mesa 10 03/01/2020
Mesa 20 04/01/2020
Mesa 30 05/01/2020
Mesa 40 06/01/2020
Mesa 50 07/01/2020
Mesa 60 08/01/2020
Mesa 70 09/01/2020

Outra tabela tem duas regras para cada item sobre quantos dias são usados ​​para calcular os valores da soma contínua.

Tabela 2: Regra

item regra valor
Lâmina soma_cum 2,5
Lâmina soma_de_leads 2,5
Mesa soma_cum 3
Mesa soma_de_leads 3

Saída: cum_sum: Para Balde, data - 1/3/2020, a regra é 2,5 e, portanto, o valor = 10+20+30 * 0,5 lead_sum: Para Balde, data - 1/3/2020, a regra é 2,5 e, portanto, o valor = 20+30+40 * 0,5

Como escrevo a consulta para considerar valores parciais para a última data?

item estoque data soma_cum soma_de_leads
Lâmina 10 03/01/2020 45 70
Lâmina 20 04/01/2020 70 95
Lâmina 30 05/01/2020 95 120
Lâmina 40 06/01/2020 120 145
Lâmina 50 07/01/2020 145 130
Lâmina 60 08/01/2020 130 70
Lâmina 70 09/01/2020 70 0
Mesa 10 03/01/2020 60 90
Mesa 20 04/01/2020 90 120
Mesa 30 05/01/2020 120 150
Mesa 40 06/01/2020 150 180
Mesa 50 07/01/2020 180 130
Mesa 60 08/01/2020 130 70
Mesa 70 09/01/2020 70 0

https://sqlfiddle.com/postgresql/online-compiler?id=c87e6a47-0949-4781-b8b5-3559929a063d

postgresql
  • 1 1 respostas
  • 39 Views

1 respostas

  • Voted
  1. Best Answer
    Erwin Brandstetter
    2024-10-06T06:44:49+08:002024-10-06T06:44:49+08:00

    Uma função de janela com uma moldura personalizada vem à mente, como:

    ... sum(stock) OVER (ORDER BY date ROWS BETWEEN CURRENT ROW AND _offset FOLLOWING)
    

    Mas há duas questões :

    1. _offseta cláusula in the frame não permite variáveis.

    2. _offseta cláusula in the frame não processa números fracionários. Se você passar um tipo numérico com parte fracionária, ele será arredondado na conversão para inteiro. Isso é particularmente problemático com tipos de ponto flutuante como double precision, onde 2,5 pode ser arredondado para 2 (!) devido ao armazenamento inexato do valor. (Eu não envolveria tipos de ponto flutuante nesses tipos de cálculo para começar!)

    O manual:

    Nas opções de quadro and , the deve ser uma expressão que não contenha nenhuma variável, função de agregação ou função de janela. O significado de the depende do modo de quadro:offset PRECEDINGoffset FOLLOWINGoffsetoffset

    • No ROWSmodo, o offsetdeve produzir um inteiro não nulo e não negativo, e a opção significa que o quadro inicia ou termina o número especificado de linhas antes ou depois da linha atual.

    Para contornar o problema 1, faça um loop nos itens e execute SQL dinâmico em PL/pgSQL.

    Para contornar o problema 2, trunque o limite superior e adicione outro valor lead()multiplicado pelo restante:

    Assumindo integridade referencial, e todas as colunas não NOT NULLe valores no intervalo permitido. Senão, você precisa fazer mais.

    CREATE OR REPLACE FUNCTION my_rolling_sum(_items text[] = null)
      RETURNS TABLE (
       item     text
     , stock    numeric
     , date     date
     , cum_sum  numeric
     , lead_sum numeric
       )
      LANGUAGE plpgsql AS
    $func$
    DECLARE
       _rule record;
       _sql text;
    BEGIN
       FOR _rule IN
          SELECT r.item
               , any_value(r.value) FILTER (WHERE r.rule = 'cum_sum') AS cum_value
               , any_value(r.value) FILTER (WHERE r.rule = 'lead_sum') AS lead_value
          FROM   rule r
          WHERE (_items IS NULL OR r.item = ANY(_items))
          GROUP  BY r.item
          ORDER  BY r.item  -- ? suppose that's the desired order?
       LOOP
          _sql := format(
             $q$
             SELECT s.item, s.stock, s.date
                  , round (         sum(s.stock) OVER (ORDER BY s.date ROWS BETWEEN CURRENT ROW AND %1$s FOLLOWING)
                         + lead(s.stock, %1$s + 1, 0) OVER (ORDER BY s.date) * $1
                         , 2)  -- AS cum_sum
                  , round (COALESCE(sum(s.stock) OVER (ORDER BY s.date ROWS BETWEEN 1 FOLLOWING AND %2$s FOLLOWING), 0)
                         + lead(s.stock, %2$s + 1, 0) OVER (ORDER BY s.date) * $2 
                         , 2)  -- AS lead_sum
             FROM   stock s
             WHERE  s.item = %3$L
             $q$
           , trunc(_rule.cum_value) - 1
           , trunc(_rule.lead_value)
           , _rule.item
           );
    
    --    RAISE NOTICE '%', _sql;    -- debug?
          RETURN QUERY EXECUTE _sql  -- execute
          USING _rule.cum_value::numeric % 1
              , _rule.lead_value::numeric % 1;  --  % 1 gets fractional remainder
       END LOOP;
    END
    $func$;
    

    violino

    Solicite todos os itens:

    SELECT * FROM my_rolling_sum();  -- no argument
    

    Solicitação de itens fornecidos:

    SELECT * FROM my_rolling_sum('{Blade}');
    

    Certifique-se de ter um índice stock(item)para tornar isso rápido. Idealmente em stock(item, date) INCLUDE (stock), mas isso pode ser muito especializado.

    A função agregada any_value()foi adicionada com o Postgres 16. Substitua por min()em versões mais antigas. (E lembre-se de declarar sua versão do Postgres em todas as perguntas.)

    Produz seu resultado. Há sutilezas com arredondamento, tratamento de nulos, ordem de classificação e exibição, que a pergunta não esclareceu.

    • 1

relate perguntas

  • Posso ativar o PITR depois que o banco de dados foi usado

  • Práticas recomendadas para executar a replicação atrasada do deslocamento de tempo

  • Os procedimentos armazenados impedem a injeção de SQL?

  • Sequências Biológicas do UniProt no PostgreSQL

  • Qual é a diferença entre a replicação do PostgreSQL 9.0 e o Slony-I?

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