DISTINCT ON(Postgres)与 QUALIFY(Snowflake)

问题描述 投票:0回答:3

我尝试在 Snowflake 中使用 QUALIFY 子句,因为它不支持像 Postgres 那样使用 DISTINCT ON。然而,当我在查询中使用 QUALIFY 子句时,它会返回与 Postgres 中不同的结果,并且每次我针对数千条记录的结果集运行此雪花时,它都会返回不同的答案,而如果我运行数百条记录,它会返回不同的答案。记录它每次都提供正确的结果。而在 Postgres 中,无论结果集的大小如何,它每次都会返回正确的结果。根据这些页面:

在 Snowflake 中使用`DISTINCT ON`

https://community.snowflake.com/s/question/0D50Z00008NrIYuSAN/whats-the-equivalent-of-distinct-on-in-snowflake-

DISTINCT ON 和 QUALIFY 应该以相同的方式工作,所以我不太确定为什么我有不同的结果?

雪花:

SELECT wallet_transaction.walletId,
       wallet_transaction.balance,
       wallet_transaction.transactionDate,
       wallet_transaction.parkerId,
       wallet_transaction.operatorName,
       wallet_transaction.operatorId,
       wallet_transaction.offerName,
       wallet_transaction.offerId
FROM wallet_transaction
WHERE {% condition snapshot_date %} wallet_transaction.transactionDate {% endcondition %}
QUALIFY ROW_NUMBER() OVER (PARTITION BY wallet_transaction.walletId
ORDER BY wallet_transaction.walletId, wallet_transaction.transactionDate DESC) = 1;

Postgres:

SELECT DISTINCT ON(wallet_transaction.walletId)
       wallet_transaction.walletId,
       wallet_transaction.balance,
       wallet_transaction.transactionDate,
       wallet_transaction.parkerId,
       wallet_transaction.operatorName,
       wallet_transaction.operatorId,
       wallet_transaction.offerName,
       wallet_transaction.offerId
FROM wallet_transaction
WHERE {% condition snapshot_date %} wallet_transaction.transactionDate {% endcondition %}
ORDER BY wallet_transaction.walletId,wallet_transaction.transactionDate DESC;
postgresql snowflake-cloud-data-platform greatest-n-per-group
3个回答
1
投票

wallet_transaction.walletId
ORDER BY
row_number()
子句中是多余的,但这无法解释你的观察结果。

还假设你的不透明

WHERE
条件没有以某种方式被破坏。

每个

(walletId, transactionDate)

重复
可以解释它。那么结果是任意的,并且可以在执行之间改变而无需更改表。 Postgres 通常从重复项中按物理排序顺序选取第一行。 Snowflake 具有完全不同的存储架构,并且可能会得到不同的选择。

如果

UNIQUE
可以是
(walletId, transactionDate)
,甚至对
transactionDate
施加
NULL
约束也会发生这种情况,因为
NULL
出于
UNIQUE
约束的目的比较不同(根据 SQL 标准)。参见:

如果是这样,请添加更多

ORDER BY
表达式以使排序顺序确定性。表的 PK 列可以做到这一点 - 假设
transaction_id
缺乏声明。然后,如果出现重复,您将获得具有最小
transaction_id
的行。适用于 Postgres 和 Snowflake。

雪花:

SELECT walletId
     , balance
     , transactionDate
     , parkerId
     , operatorName
     , operatorId
     , offerName
     , offerId
FROM   wallet_transaction w
WHERE  {% condition snapshot_date %} transactionDate {% endcondition %}
QUALIFY row_number() OVER (PARTITION BY walletId
                           ORDER BY transactionDate DESC, transaction_id) = 1;

Postgres:

SELECT DISTINCT ON (walletId)
       walletId
     , balance
     , transactionDate
     , parkerId
     , operatorName
     , operatorId
     , offerName
     , offerId
FROM   wallet_transaction w
WHERE  {% condition snapshot_date %} transactionDate {% endcondition %}
ORDER  BY walletId, transactionDate DESC, transaction_id;

参见:


0
投票

ROW_NUMBER() OVER (PARTITION BY wallet_transaction.walletId ORDER BY wallet_transaction.walletId, wallet_transaction.transactionDate DESC) 
对于 PARTITION BY 和 ORDER BY 上都存在的列
wallet_transaction.walletId
没有意义。

SELECT
    wallet_transaction.walletId,
    wallet_transaction.balance,
    wallet_transaction.transactionDate,
    wallet_transaction.parkerId,
    wallet_transaction.operatorName,
    wallet_transaction.operatorId,
    wallet_transaction.offerName,
    wallet_transaction.offerId
FROM wallet_transaction
WHERE {% condition snapshot_date %} wallet_transaction.transactionDate {% endcondition %}
QUALIFY ROW_NUMBER() OVER (PARTITION BY wallet_transaction.walletId
       ORDER BY wallet_transaction.transactionDate DESC) = 1;

这意味着仅列

wallet_transaction.transactionDate
并不能提供稳定排序


可以通过检查由 PARTITION 和 ORDER BY 子句中存在的所有列分区的窗口

COUNT
来确认:

SELECT
    wallet_transaction.walletId,
    wallet_transaction.balance,
    wallet_transaction.transactionDate,
    wallet_transaction.parkerId,
    wallet_transaction.operatorName,
    wallet_transaction.operatorId,
    wallet_transaction.offerName,
    wallet_transaction.offerId
FROM wallet_transaction
WHERE {% condition snapshot_date %} wallet_transaction.transactionDate {% endcondition %}
QUALIFY COUNT() OVER (PARTITION BY wallet_transaction.walletId,
                      wallet_transaction.transactionDate DESC) > 1;

0
投票

您面临排序顺序的不确定性条件。基本上,如果您按有重复项的 B 列进行排序,则 C 列可以返回 Snowflake 可接受的任何结果。例如下表:

A  B   C 1  boy tall 1  boy short 2  boy average

如果您采用在 A 上分区的查询的第一个值并按 B 排序,则由于排序列 (B) 中存在重复项,每次运行 C 列将具有不同的值。

© www.soinside.com 2019 - 2024. All rights reserved.