我尝试在 Snowflake 中使用 QUALIFY 子句,因为它不支持像 Postgres 那样使用 DISTINCT ON。然而,当我在查询中使用 QUALIFY 子句时,它会返回与 Postgres 中不同的结果,并且每次我针对数千条记录的结果集运行此雪花时,它都会返回不同的答案,而如果我运行数百条记录,它会返回不同的答案。记录它每次都提供正确的结果。而在 Postgres 中,无论结果集的大小如何,它每次都会返回正确的结果。根据这些页面:
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;
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;
参见:
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;
您面临排序顺序的不确定性条件。基本上,如果您按有重复项的 B 列进行排序,则 C 列可以返回 Snowflake 可接受的任何结果。例如下表:
A B C 1 boy tall 1 boy short 2 boy average
如果您采用在 A 上分区的查询的第一个值并按 B 排序,则由于排序列 (B) 中存在重复项,每次运行 C 列将具有不同的值。