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 / 270521
Accepted
tony
tony
Asked: 2020-07-07 19:23:47 +0800 CST2020-07-07 19:23:47 +0800 CST 2020-07-07 19:23:47 +0800 CST

Soma todos os valores exclusivos de datas anteriores

  • 772

Digamos que, para simplificar, eu tenha a seguinte tabela:

id      amount     p_id     date
------------------------------------------------
1       5          1        2020-01-01T01:00:00
2       10         1        2020-01-01T01:10:00 
3       15         2        2020-01-01T01:20:00 
4       10         3        2020-01-01T03:30:00 
5       10         4        2020-01-01T03:50:00 
6       20         1        2020-01-01T03:40:00

Aqui está um exemplo de resposta que eu quero:

{
 "2020-01-01T01:00:00": 25, -- this is from adding records with ids: 2 and 3
 "2020-01-01T03:00:00": 55  -- this is from adding records with ids: 3,4,5 and 6
}

Eu quero obter o total ( sum(amount)) de todos os exclusivos p_idagrupados por hora.

A linha escolhida por p_idé aquela com o último date. Por exemplo, o primeiro valor na resposta acima não inclui id 1porque o registro com id 2tem o mesmo p_ide o datedessa linha é posterior.

A única coisa complicada é que eu quero incluir a soma de todos os amountpor p_idse eles dateforem antes da hora apresentada. Por exemplo, no segundo valor da resposta (com a chave "2020-01-01T03:00:00"), embora id 3tenha um carimbo de data/hora em uma hora diferente, é o mais recente para isso p_id 2e, portanto, é incluído na soma de "2020-01-01T03:00:00". Mas a linha com id 6substituições id 2com o mesmo p_id 1.

Em outras palavras: sempre pegue o último amountpara cada p_idaté o momento e calcule a soma para cada hora distinta encontrada na tabela.

postgresql greatest-n-per-group
  • 2 2 respostas
  • 208 Views

2 respostas

  • Voted
  1. Akina
    2020-07-07T21:12:29+08:002020-07-07T21:12:29+08:00

    Olhe para

    WITH cte AS ( SELECT *, ROW_NUMBER() OVER (PARTITION BY p_id ORDER BY date DESC) rn
                  FROM source_table
                  WHERE date_trunc('hour', date) = @needed_datetime_truncated_to_hour )
    SELECT @needed_datetime_truncated_to_hour, SUM(amount)
    FROM cte
    WHERE rn = 1;
    
    • 1
  2. Best Answer
    Erwin Brandstetter
    2020-07-08T05:20:05+08:002020-07-08T05:20:05+08:00

    Caso simples

    Obter a soma para uma única hora é relativamente simples:

    SELECT timestamp '2020-01-01 03:00:00', sum(amount)
    FROM  (
       SELECT DISTINCT ON (p_id) amount
       FROM   tbl
       WHERE  date < timestamp '2020-01-01 03:00:00' + interval '1h'
       ORDER  BY p_id, date DESC
       ) sub;
    

    DISTINCT ONnormalmente é substancialmente mais rápido que a subconsulta/CTE com row_number(). Ver:

    • SELECT DISTINCT ON, ordenado por outra coluna

    Para muitas linhas por p_id, há potencial para otimizar um pouco mais com a indexação inteligente e uma consulta correspondente. Ver:

    • Otimize a consulta GROUP BY para recuperar a última linha por usuário
    • Selecione a primeira linha em cada grupo GROUP BY?

    Soma corrida especial para cada hora

    Você parece querer a soma para cada hora distinta na tabela .

    Você pode simplesmente destilar horas distintas e aplicar a solução simples a cada uma delas em uma LATERALsubconsulta:

    WITH grid AS (  -- or some other source?
       SELECT DISTINCT date_trunc('hour', date) AS hour
       FROM   tbl
       )
    SELECT *
    FROM   grid
    CROSS  JOIN LATERAL (
       SELECT sum(amount)
       FROM  (
          SELECT DISTINCT ON (p_id) amount
          FROM   tbl
          WHERE  date < grid.hour + interval '1h'
          ORDER  BY p_id, date DESC
          ) sub1
       ) sub2
    ORDER  BY grid.hour;
    

    Deve ficar bem enquanto não há muitas horas distintas. Mas a consulta não escala muito bem . O último amountpara cada p_idé calculado com o custo total (aumentando continuamente) para cada hora adicional.

    Otimize a soma acumulada por muitas horas

    Espero que esse CTE recursivo escale melhor (com uma sobrecarga considerável inicialmente), pois ele só precisa se unir a uma linha p_ida cada próxima hora:

    WITH RECURSIVE
      values AS (
       SELECT DISTINCT ON (1, 2)
              date_trunc('hour', date) AS hour, p_id, amount
       FROM   tbl
       ORDER  BY 2, 1, date DESC  -- !
       )
    , hours AS (
       SELECT hour, row_number() OVER (ORDER BY hour) AS hnr
       FROM  (SELECT DISTINCT hour FROM values) sub
       )
    , cte AS (
       SELECT p_id, h.hour, v.amount, 2 AS next_hnr
       FROM  (SELECT DISTINCT p_id FROM values) i  -- all IDs
       JOIN   hours       h ON hnr = 1             -- first hour
       LEFT   JOIN values v USING (p_id, hour)
    
       UNION ALL
       SELECT c.p_id, h.hour, COALESCE(v.amount, c.amount), c.next_hnr + 1
       FROM   cte         c
       JOIN   hours       h ON h.hnr  = c.next_hnr
       LEFT   JOIN values v ON v.p_id = c.p_id
                           AND v.hour = h.hour
       )
    SELECT hour, sum(amount)
    FROM   cte
    GROUP  BY 1
    ORDER  BY 1;
    

    Além disso, pode haver mais potencial para otimizar, dependendo da distribuição de valor, como indicado para o caso simples no topo.

    db<>fique aqui

    Além disso: chamar sua timestampcoluna de "data" é bastante enganoso, pois é um tipo de dados básico diferente.

    • 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