我怎样才能获得每个国家的最大值

Posted

技术标签:

【中文标题】我怎样才能获得每个国家的最大值【英文标题】:how can i get max value for each country 【发布时间】:2018-04-28 14:13:02 【问题描述】:

我正在使用 oracle sql 开发人员。我有两张桌子

交易:

╔════╤═══════╗
║ id │ value ║
╠════╪═══════╣
║ 1  │ 10    ║
╟────┼───────╢
║ 1  │ 20    ║
╟────┼───────╢
║ 2  │ 30    ║
╟────┼───────╢
║ 3  │ 40    ║
╚════╧═══════╝

和用户:

╔════╤═════════╤═════╗
║ id │ country │ sex ║
╠════╪═════════╪═════╣
║ 1  │ Germany │ m   ║
╟────┼─────────┼─────╢
║ 2  │ Germany │ f   ║
╟────┼─────────┼─────╢
║ 3  │ France  │ m   ║
╚════╧═════════╧═════╝

我想像这样为每个国家/地区获得最大值

╔════╤═════════╤═════╤══════════╗
║ id │ country │ sex │ maxvalue ║
╠════╪═════════╪═════╪══════════╣
║ 2  │ Germany │ f   │ 30       ║
╟────┼─────────┼─────┼──────────╢
║ 3  │ France  │ m   │ 40       ║
╚════╧═════════╧═════╧══════════╝

我知道如何为每个用户获取最大值并加入表格

SELECT u.*, max
FROM users u
LEFT JOIN
(SELECT id, max(value) as max
FROM transactions 
group by ID) t
on u.id = t.id;

我应该改变什么以获得每个国家的最大值?

【问题讨论】:

德国米在哪里? 如果事务表中 id = 1 的值为 20、30,那么预期的输出是什么?它会取代法国到德国吗? 应该同时显示 Id 1 的值也是 30 (10 + 20)。因此,id 1 和 id 2 的最大值是相同的。所以现在怎么办?为什么我们选择 2 或 1? 只有其中一个 【参考方案1】:

这可能有效:

SELECT id, country, sex, value AS maxvalue FROM (
    SELECT u.id, u.country, u.sex, COALESCE(t.value, 0) AS value
         , ROW_NUMBER() OVER ( PARTITION BY u.country ORDER BY t.value DESC NULLS LAST ) AS rn
      FROM users u LEFT JOIN transactions t
        ON u.id = t.id
) WHERE rn = 1;

这将获取每个国家/地区的所有值并对其进行排名,然后仅检索排名最高的值。如果您也想打成平手,请使用RANK() 而不是ROW_NUMBER()

SELECT id, country, sex, value AS maxvalue FROM (
    SELECT u.id, u.country, u.sex, COALESCE(t.value, 0) AS value
         , RANK() OVER ( PARTITION BY u.country ORDER BY t.value DESC NULLS LAST ) AS rn
      FROM users u LEFT JOIN transactions t
        ON u.id = t.id
) WHERE rn = 1;

希望这会有所帮助。

【讨论】:

【参考方案2】:

试试这个。

select tmp.country, tmp.maxvalue, tmp.id, users.sex from (
select users.country as country, max(transactions.value) as maxvalue, max(users.id) as id 
from users
inner join transactions on users.id = transactions.id
group by users.country) tmp
inner join users on tmp.id = users.id;

演示:http://www.sqlfiddle.com/#!4/5f476/27/0

【讨论】:

【参考方案3】:

传统方法不会使用子查询,而只是使用joingroup by

SELECT u.country, MAX(t.value)
FROM users u LEFT JOIN
     transactions t
     ON u.id = t.id
GROUP BY u.country;

【讨论】:

可能是 OP 也想通过 sex 分组。示例预期数据与文本说明不匹配。 您的代码有效,但仅当我想显示国家和最大值时,当我想显示国家、最大值和性别时,我得到一个错误 - “错误报告 - SQL 错误:ORA-00979:不是 GROUP BY 表达式 00979. 00000 - "不是 GROUP BY 表达式"" 嗨@gordonLinoff,我告诉过你;) 我不想按性别分组,但我想在表格中显示它 是的,很有趣。我期待这个线程的结束。我去吃爆米花。【参考方案4】:

这可能会得到所需的结果

SELECT u.id, u.country, u.sex, MAX(t.value)
FROM users u 
LEFT JOIN transactions t ON u.id = t.id
GROUP BY u.id, u.country, u.sex;

【讨论】:

您的代码不起作用,它不显示每个国家/地区的最大值 我的查询显示 countrysex 的最大值,如果您只想要国家/地区的值而不是从两者中删除 u.id 和 u.sex select 和 group by 子句 错误报告 - SQL 错误:ORA-00979:不是 GROUP BY 表达式 00979。00000 - “不是 GROUP BY 表达式” *原因:*操作: 当您在使用聚合函数时,在 group by 子句中没有选定子句的所有字段时,会发生此错误。见this 我的真实桌子要大得多,而且我有超过 2 种性别【参考方案5】:

您必须首先找到每个国家/地区的最大值,然后再为性别进行连接,如下所示:

SELECT u.*, t.value
FROM transactions t
INNER JOIN users u ON t.id = u.id
INNER JOIN
(SELECT us.country, MAX(tr.value) AS max_value
 FROM transactions tr
 INNER JOIN users us ON tr.id = us.id
 GROUP BY us.country) sub ON t.value = sub.value AND u.country = sub.country

【讨论】:

【参考方案6】:
select * from (
SELECT t.ID, u.COUNTRY, T.VALUE, 
row_number() over(partition by u.country order by t.value desc) rn
FROM USERS u , transactions t
where u.id = t.id)
where rn = 1

【讨论】:

以上是关于我怎样才能获得每个国家的最大值的主要内容,如果未能解决你的问题,请参考以下文章

tyvj 1203 机器分配

我怎样才能有效地找到在预算范围内并最大化效用的活动子集?

洛谷 p2066 机器分配

P2066 机器分配

洛谷P2066 机器分配

洛谷 P2066 机器分配