em Uncategorized

SQL – como agrupar registros por uma coluna e pegar o último pela data

Não sou bom com SQL – nunca fui, nunca quis me aprofundar e tenho um certo bloqueio com relação a isso.
Mas, algumas vezes tenho que mexer com isso, e sempre me deparo com alguns erros bobos ou algumas coisas mais complexas.

No caso, incrivelmente as questões bobas não me atrapalharam, mas quebrei a cabeça quando tinha uma tabela com uma estrutura mais ou menos semelhante a essa (vou suprimir as colunas que não interessam para o problema):

  • id: id primário, auto-incremente
  • f_id: é uma relação de cada registro com registros de outra tabela. Não é único
  • adddate: data do registro
  • nome: nome do registro

Minha necessidade era agrupar os registros por esse f_id e retornar a data mais recente de cada grupo.
À princípio estava tentando fazer um SELECT e agrupar por GROUP BY, dando um ORDER BY depois, mas percebi que uma vez usado o GROUP BY nada garante qual é o registro que ele vai usar quando der um ORDER BY.
Vi então que a coisa seria mais séria, e que teria que usar SUBSELECTS… estava quebrando a cabeça e o Alexandre (@kurko) me ajudou após um pedido de SOS pelo twitter, e a seguinte query abaixo me salvou!

SELECT u.f_id, u.nome, ( SELECT adddate FROM usuario AS t WHERE t.f_id=u.f_id ORDER BY t.adddate DESC LIMIT 1) as data FROM usuario AS u GROUP BY u.f_id ORDER BY u.f_id

Espero que seja de utilidade!

Escreva um comentário

Comentário

  1. SELECT
    PRODUTO,
    DESCR,
    UM,
    SUM(ISNULL(PRECO,0)) PRECO,
    SUM(ISNULL(CUSTO,0)) CUSTO,
    SUM(ISNULL(ESTOQUE,0)) ESTOQUE,
    SUM(ISNULL(C_NOVAS_COMPRAS,0)) C_NOVAS_COMPRAS,
    VALIDADE_NOVAS_COMPRAS,
    SUM(C_MERCADO) C_MERCADO,
    VALIDADE_MERCADO

    FROM
    (
    SELECT
    DA1_CODPRO PRODUTO,
    B1_DESC DESCR,
    B1_UM UM,
    DA1_PRCVEN PRECO,
    0 CUSTO,
    0 ESTOQUE,
    0 C_NOVAS_COMPRAS,
    ” VALIDADE_NOVAS_COMPRAS,
    0 C_MERCADO,
    ” VALIDADE_MERCADO

    FROM
    DA1010 DA1 WITH(NOLOCK)
    INNER JOIN SB1010 SB1 WITH(NOLOCK) ON
    B1_FILIAL = ”
    AND B1_COD = DA1_CODPRO
    AND SB1.D_E_L_E_T_ ‘*’

    WHERE
    DA1.D_E_L_E_T_ ‘*’
    AND DA1_CODTAB = ‘F01’

    UNION ALL
    SELECT
    CODIGO,
    DESCRICAO,
    UM,
    0 PRECO,
    CUSTO,
    ESTOQUE,
    0 C_NOVAS_COMPRAS,
    ” VALIDADE_NOVAS_COMPRAS,
    0 C_MERCADO,
    ” VALIDADE_MERCADO

    FROM
    DwFuturagro.DBO.TB_ESTXCUSTO
    INNER JOIN DA1010 DA1 WITH(NOLOCK) ON
    FILIAL = ‘031’
    AND CODIGO = DA1_CODPRO
    AND DA1_CODTAB = ‘F01’
    AND DA1.D_E_L_E_T_ ‘*’

    UNION ALL

    SELECT
    ZBQ_COD PRODUTO,
    ZBQ_DESC DESCR,
    B1_UM UM,
    0 PRECO,
    0 CUSTO,
    0 ESTOQUE,
    ZBQ_CUSTO C_NOVAS_COMPRAS,
    ZBQ_VALCUS VALIDADE_NOVAS_COMPRAS,
    ZBQ_CUSMER C_MERCADO,
    ZBQ_VALCME VALIDADE_MERCADO
    FROM
    ZBQ010 ZBQ WITH(NOLOCK)
    LEFT JOIN SB1010 SB1 WITH(NOLOCK) ON
    B1_FILIAL = ”
    AND B1_COD = ZBQ_COD
    AND SB1.D_E_L_E_T_ ‘*’
    WHERE
    ZBQ.D_E_L_E_T_ ‘*’
    ) TRB
    WHERE PRODUTO = ‘100000209380126’
    GROUP BY
    PRODUTO,
    DESCR,
    UM,
    VALIDADE_NOVAS_COMPRAS,
    VALIDADE_MERCADO

    Resultado
    –Como faço para unificar essas duas linhas?
    PRODUTO DESCR UM PRECO CUSTO ESTOQUE C_NOVAS_COMPRAS VALIDADE_NOVAS_COMPRAS C_MERCADO VALIDADE_MERCADO
    100000209380126 FLAK 200 SL BD 20 LTS – OR-2 L 19,44 16,17 60 0 0
    100000209380126 FLAK 200 SL BD 20 LTS – OR-2 L 0 0 0 0 20191207 11,1 20191207