Presto: é MAX_BY () determinístico

Nov 07 2020

É a função MAX_BY()determinística. Se eu usar MAX_()para duas colunas diferentes, ambas dependendo de uma terceira, obterei o mesmo resultado de linha?

A documentação presto não menciona isso. Esta documentação sobre o mysql menciona que não, então não tenho certeza de onde encontrar essa informação.

Testei rapidamente com o seguinte:

WITH my_table(id, arr, something) AS (
    VALUES
        (1, ARRAY['one'], 0.0),
        (2, ARRAY['two'], 0.0),
        (3, ARRAY['three'], 0.0),
        (4, ARRAY['four'], 0.0),
        (5, ARRAY['five'], 0.0),
        (6, ARRAY[''], 0.0)
)
SELECT
    MAX_BY(id,something),
    MAX_BY(arr,something)
FROM my_table

Ele retornou a primeira linha, então não parece arbitrário, mas também não prova coisas.

Alguém aí pode ajudar?

Há uma questão relacionada a retornar várias colunas de uma única, MAX_BY()então estou pensando que preciso usar essa solução para garantir que o atributo da mesma linha seja selecionado: max_by com várias colunas de retorno

Respostas

3 MartinTraverso Nov 07 2020 at 02:23

Não, em caso de empate, o resultado de max_bye min_byé arbitrário. Pode parecer determinístico, mas não é um comportamento definido e pode mudar em algum ponto.

Se quiser que todos os valores sejam consistentes, você deve usar o truque ao qual se referiu, em que você empacota todas as colunas de interesse em um único valor do tipo ROW:

SELECT max_by((x1, x2, x3), y) r
FROM (...) t(y, x1, x2, x3)
1 GMB Nov 07 2020 at 01:46

Provavelmente é mais seguro e mais eficiente usar funções de janela:

select *
from (
    select t.*, row_number() over(order by something desc) rn
    from my_table t
) t
where rn = 1

Para este caso simples, uma cláusula de limitação de linha é realmente boa o suficiente:

select *
from my_table 
order by something desc
limit 1

Ambas as consultas garantem que todos os valores retornados pertencem à mesma linha.

Nenhum, entretanto, é determinístico, no sentido de que execuções consecutivas da mesma consulta podem retornar uma linha diferente. Se você deseja um resultado estável, precisa de uma coluna (ou conjunto de colunas) que possa ser usada para identificar de forma única cada linha: adicionar idà order bycláusula seria ótimo aqui.