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 / 184538
Accepted
Alin
Alin
Asked: 2017-08-29 14:07:49 +0800 CST2017-08-29 14:07:49 +0800 CST 2017-08-29 14:07:49 +0800 CST

Possível obter ledger de histórico (saldo) com consulta sql?

  • 772

Não tenho certeza se este é o lugar para perguntar, mas aqui vai. Estou usando um servidor Postgres e para simplificar, vou tentar mostrar um breve cenário do que preciso.

CREATE TABLE operations(id,type,item,price,amount)
 AS VALUES
  ( 1::int, 'buy' , 'item1',  2, 10::int ),
  ( 2::int, 'buy' , 'item1',  3,  4::int ),
  ( 3::int, 'sell', 'item1',  4, 12::int )
;
  • Se eu passar por uma base de custo FIFO, o livro-razão ou saldos após cada pedido deve se parecer com:

    id  |  price   | amount |
    
    1   |      2   |     10 |
    
    2   |      2   |     10 |
        |      3   |      4 |
    
    3   |      3   |      2 |
    

Uma coisa que tentei é ter uma tabela como operation_balances na qual para cada operação processada eu insiro o saldo correspondente. Isso funciona, no entanto, há um problema com a enorme quantidade de saldos inseridos para um grande número de operações, portanto, não é uma solução válida. Eu queria saber se é possível obter a parte do saldo de cada pedido como parte de uma consulta sql. Pode demorar um pouco para ser executado, mas economizaria muito espaço no banco de dados.

postgresql
  • 1 1 respostas
  • 523 Views

1 respostas

  • Voted
  1. Best Answer
    Evan Carroll
    2017-08-29T18:03:24+08:002017-08-29T18:03:24+08:00

    Para começar, e isso é apenas para levá-lo a algum lugar,

    SELECT *,
      jsonb_agg(jsonb_build_object('p',price,'a',amount))
        FILTER (WHERE type='buy')
        OVER (PARTITION BY item ORDER BY id)
        AS cumpurchased
    FROM operations;
     id | type | item  | price | amount |             cumpurchased              
    ----+------+-------+-------+--------+---------------------------------------
      1 | buy  | item1 |     2 |     10 | [{"a": 10, "p": 2}]
      2 | buy  | item1 |     3 |      4 | [{"a": 10, "p": 2}, {"a": 4, "p": 3}]
      3 | sell | item1 |     4 |     12 | [{"a": 10, "p": 2}, {"a": 4, "p": 3}]
    

    Aqui, nós serializamos as compras em arquivos cumpurchased. Isso parece simples, agora podemos explodir isso expandindo cumpurchasedpara as transações individuais.

    SELECT id, type, item, price, amount, cumsale, e, eid
    FROM (
            SELECT *,
                    sum(amount) FILTER (WHERE type='sell') OVER (PARTITION BY id) AS cumsale,
            jsonb_agg(jsonb_build_object('p',price,'a',amount))
                            FILTER (WHERE type='buy')
            OVER (PARTITION BY item ORDER BY id)
            AS cumpurchased
            FROM operations
    ) AS with_agg
    CROSS JOIN LATERAL jsonb_array_elements(cumpurchased)
            WITH ORDINALITY
            AS jsonb(e,eid)
    ORDER BY id, eid;
     id | type | item  | price | amount | cumsale |         e         | eid 
    ----+------+-------+-------+--------+---------+-------------------+-----
      1 | buy  | item1 |     2 |     10 |         | {"a": 10, "p": 2} |   1
      2 | buy  | item1 |     3 |      4 |         | {"a": 10, "p": 2} |   1
      2 | buy  | item1 |     3 |      4 |         | {"a": 4, "p": 3}  |   2
      3 | sell | item1 |     4 |     12 |      12 | {"a": 10, "p": 2} |   1
      3 | sell | item1 |     4 |     12 |      12 | {"a": 4, "p": 3}  |   2
    (5 rows)
    

    Você deveria estar ale para ver onde estou indo com isso...

    SELECT id,type,item,e,eid,sum(
            (e->>'a')::int
    ) OVER (PARTITION BY id ORDER BY eid)
            - coalesce(cumsale,0)
      AS qty_remaining
    FROM (
            SELECT *,
                    sum(amount) FILTER (WHERE type='sell') OVER (PARTITION BY id) AS cumsale,
            jsonb_agg(jsonb_build_object('p',price,'a',amount))
                            FILTER (WHERE type='buy')
            OVER (PARTITION BY item ORDER BY id)
            AS cumpurchased
            FROM operations
    ) AS with_agg
    CROSS JOIN LATERAL jsonb_array_elements(cumpurchased)
            WITH ORDINALITY
            AS jsonb(e,eid);
     id | type | item  |         e         | eid | qty_remaining 
    ----+------+-------+-------------------+-----+---------------
      1 | buy  | item1 | {"a": 10, "p": 2} |   1 |            10
      2 | buy  | item1 | {"a": 10, "p": 2} |   1 |            10
      2 | buy  | item1 | {"a": 4, "p": 3}  |   2 |            14
      3 | sell | item1 | {"a": 10, "p": 2} |   1 |            -2
      3 | sell | item1 | {"a": 4, "p": 3}  |   2 |             2
    (5 rows)
    

    A partir deste ponto, você precisa filtrar o -2, envolvemos a consulta novamente e colocamos essa condicional lá. Então nós apenas selecionamos a partir disso.

    SELECT id, e->>'p' AS price, least(qty_remaining,(e->>'a')::int) AS amount
    FROM (
          SELECT id,type,item,e,eid,sum(
            (e->>'a')::int
          ) OVER (PARTITION BY id ORDER BY eid)
            - coalesce(cumsale,0)
            AS qty_remaining
          FROM (
            SELECT *,
              sum(amount) FILTER (WHERE type='sell') OVER (PARTITION BY id) AS cumsale,
              jsonb_agg(jsonb_build_object('p',price,'a',amount))
                FILTER (WHERE type='buy')
                OVER (PARTITION BY item ORDER BY id)
                AS cumpurchased
            FROM operations
          ) AS with_agg
          CROSS JOIN LATERAL jsonb_array_elements(cumpurchased)
            WITH ORDINALITY
            AS jsonb(e,eid)
          ) AS t
    WHERE qty_remaining > 0;
     id | price | amount 
    ----+-------+--------
      1 | 2     |     10
      2 | 2     |     10
      2 | 3     |      4
      3 | 3     |      2
    (4 rows)
    
    • 0

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