Postgresql 为每个类型找到最大值 transaction_id 给出重复项(当它不应该用于 PK 时)
Postgresql finding max transaction_id for each type giving duplicates (when it's not supposed to for PK)
问题如题;所以我有如下所示的代码来查找按卡类型交易的金额最高的 ID
SELECT tr.identifier, cc.type, tr.amount as max_amount
FROM credit_cards cc, transactions tr
WHERE (tr.amount, cc.type) IN (SELECT MAX(tr.amount), cc.type
FROM credit_cards cc, transactions tr
WHERE cc.number = tr.number
GROUP BY cc.type)
GROUP BY tr.identifier, cc.type;
当我 运行 代码时,我得到了重复的 transaction_identifier 这不应该发生,因为它是交易的 PK table;当我 运行 上面的代码如下所示时的输出
ID --------Card type--------------- Max amount
2196 "diners-club-carte-blanche" 1000.62
2196 "visa" 1000.62
11141 "mastercard" 1000.54
2378 "mastercard" 1000.54
例如上面的 2196 存在于食客全权而不是签证;
'mastercard' 是正确的,因为 2 个不同的 ID 可以有相同的最大交易。
但是,此代码应该 运行,因为 2 个 不同的 id 可能具有相同的每种类型的最大数量。
有谁知道如何防止重复出现?
这是因为 WHERE ... IN 子句匹配了最大金额或卡类型吗? (重复的是 Visa 和 Diners-Carte-Blanche,它们都具有相同的最大值 1000.62,所以我认为这是它们匹配错误的地方)
TL/DR:将WHERE cc.number = tr.number
添加到外部查询。
长版
当您在外部查询中查询 FROM table_1, table_2
并且不连接 table 时(通过连接或 where 子句),结果是 cartesian product,表示每一行来自 table_1 的每一行都与来自 table_2 的每一行相连。这与 CROSS JOIN
.
相同
因此,虽然您的内部查询有一个 where
子句和(正确地)returns 每种信用卡类型的最大值...您的外部查询没有,因此所有可能的信用组合卡和交易正在与最大值进行比较,而不仅仅是有效的。
例如,如果 cc 有三行(mastercard、visa、amex)而 tr 有三行(1、2、3),则选择“from cc, tr”会产生九行:
mastercard,1
mastercard,2
mastercard,3
visa,1
visa,2
visa,3
amex,1
amex,2
amex,3
你想要的是:
mastercard,1
visa,3
amex,2
第一行中的每一行 table 将针对第二行中的每一行重复。然后 WHERE (...) IN (...)
将 this 行集限制为仅与内部查询中的行匹配的行。可以想象,这很容易导致重复的结果。其中一些重复项正在被外部 GROUP BY
删除,一旦此问题得到解决,就不再需要了。
作为一般规则,我从不使用 join [table_1], [table_2]
并且更喜欢始终明确进行内部或外部联接(或者在某些情况下,交叉联接)以帮助避免此类问题,并且让 reader.
更清楚
SELECT tr.identifier, cc.type, tr.amount as max_amount
FROM credit_cards cc INNER JOIN transactions tr ON (cc.number = tr.number)
WHERE (tr.amount, cc.type) IN (
SELECT MAX(tr.amount), cc.type
FROM credit_cards cc
INNER JOIN transactions tr ON (cc.number = tr.number)
GROUP BY cc.type
)
注意:在平局的情况下,这将为您提供每种信用卡类型的每 笔交易的最大金额。
问题如题;所以我有如下所示的代码来查找按卡类型交易的金额最高的 ID
SELECT tr.identifier, cc.type, tr.amount as max_amount
FROM credit_cards cc, transactions tr
WHERE (tr.amount, cc.type) IN (SELECT MAX(tr.amount), cc.type
FROM credit_cards cc, transactions tr
WHERE cc.number = tr.number
GROUP BY cc.type)
GROUP BY tr.identifier, cc.type;
当我 运行 代码时,我得到了重复的 transaction_identifier 这不应该发生,因为它是交易的 PK table;当我 运行 上面的代码如下所示时的输出
ID --------Card type--------------- Max amount
2196 "diners-club-carte-blanche" 1000.62
2196 "visa" 1000.62
11141 "mastercard" 1000.54
2378 "mastercard" 1000.54
例如上面的 2196 存在于食客全权而不是签证; 'mastercard' 是正确的,因为 2 个不同的 ID 可以有相同的最大交易。
但是,此代码应该 运行,因为 2 个 不同的 id 可能具有相同的每种类型的最大数量。
有谁知道如何防止重复出现?
这是因为 WHERE ... IN 子句匹配了最大金额或卡类型吗? (重复的是 Visa 和 Diners-Carte-Blanche,它们都具有相同的最大值 1000.62,所以我认为这是它们匹配错误的地方)
TL/DR:将WHERE cc.number = tr.number
添加到外部查询。
长版
当您在外部查询中查询 FROM table_1, table_2
并且不连接 table 时(通过连接或 where 子句),结果是 cartesian product,表示每一行来自 table_1 的每一行都与来自 table_2 的每一行相连。这与 CROSS JOIN
.
因此,虽然您的内部查询有一个 where
子句和(正确地)returns 每种信用卡类型的最大值...您的外部查询没有,因此所有可能的信用组合卡和交易正在与最大值进行比较,而不仅仅是有效的。
例如,如果 cc 有三行(mastercard、visa、amex)而 tr 有三行(1、2、3),则选择“from cc, tr”会产生九行:
mastercard,1
mastercard,2
mastercard,3
visa,1
visa,2
visa,3
amex,1
amex,2
amex,3
你想要的是:
mastercard,1
visa,3
amex,2
第一行中的每一行 table 将针对第二行中的每一行重复。然后 WHERE (...) IN (...)
将 this 行集限制为仅与内部查询中的行匹配的行。可以想象,这很容易导致重复的结果。其中一些重复项正在被外部 GROUP BY
删除,一旦此问题得到解决,就不再需要了。
作为一般规则,我从不使用 join [table_1], [table_2]
并且更喜欢始终明确进行内部或外部联接(或者在某些情况下,交叉联接)以帮助避免此类问题,并且让 reader.
SELECT tr.identifier, cc.type, tr.amount as max_amount
FROM credit_cards cc INNER JOIN transactions tr ON (cc.number = tr.number)
WHERE (tr.amount, cc.type) IN (
SELECT MAX(tr.amount), cc.type
FROM credit_cards cc
INNER JOIN transactions tr ON (cc.number = tr.number)
GROUP BY cc.type
)
注意:在平局的情况下,这将为您提供每种信用卡类型的每 笔交易的最大金额。