我有一个表格,其数据看起来像这样:
data_type, value
World of Warcraft, 500
Quake 3, 1500
Quake 3, 1400
World of Warcraft, 1200
Final Fantasy, 100
Final Fantasy, 500
我想要做的是在一个语句中选择每个值的最大值。我知道我可以很容易地做一些像
这样的事情select data_type, max(value)
from table
where data_type = [insert each data type here for separate queries]
group by data_type
但我希望它显示的是
select data_type,
max(value) as 'World of Warcraft',
max(value) as 'Quake 3',
max(value) as 'Final Fantasy'
所以我在一个语句中得到每个的最大值。我该怎么做呢?
答案 0 :(得分:6)
再一次,我建议使用crosstab()
SELECT * FROM crosstab(
$$SELECT DISTINCT ON (1, 2)
'max' AS "type", data_type, val
FROM tbl
ORDER BY 1, 2, val DESC$$
,$$VALUES ('Final Fantasy'), ('Quake 3'), ('World of Warcraft')$$)
AS x ("type" text, "Final Fantasy" int, "Quake 3" int, "World of Warcraft" int)
返回:
type | Final Fantasy | Quake 3 | World of Warcraft
-----+---------------+---------+-------------------
max | 500 | 1500 | 1200
基础知识的更多解释:
PostgreSQL Crosstab Query
棘手的是让完全动态:使其适用于
至少类型众所周知:在这种情况下为integer
。
简而言之:使用当前的PostgreSQL(包括9.3)是不可能的。有approximations with polymorphic types and ways to circumvent the restrictions with arrays or hstore types。对你来说可能够好。但是在单个SQL查询中使用单个列获取结果严格来说不可能。 SQL对于类型非常严格,并且想要了解预期的内容。
但,可以使用两个查询完成。第一个构建要使用的实际查询。基于上述简单案例:
SELECT $f$SELECT * FROM crosstab(
$$SELECT DISTINCT ON (1, 2)
'max' AS "type", data_type, val
FROM tbl
ORDER BY 1, 2, val DESC$$
,$$VALUES ($f$ || string_agg(quote_literal(data_type), '), (') || $f$)$$)
AS x ("type" text, $f$ || string_agg(quote_ident(data_type), ' int, ') || ' int)'
FROM (SELECT DISTINCT data_type FROM tbl) x
这会生成您实际需要的查询。在同一事务中运行第二个以避免并发问题。
请注意quote_literal()
and quote_ident()
的战略用途,以清理各种非法(列名)名称并阻止 SQL注入。
不要被多个dollar-quoting层混淆。这对于构建动态查询是必要的。我说它尽可能简单。
答案 1 :(得分:4)
如果要在单独的列中返回每个data_type的最大值,那么您应该能够使用带有CASE表达式的聚合函数:
select
max(case when data_type='World of Warcraft' then value end) WorldofWarcraft,
max(case when data_type='Quake 3' then value end) Quake3,
max(case when data_type='Final Fantasy' then value end) FinalFantasy
from yourtable;
答案 2 :(得分:1)
如果您希望将数据聚合在单个字符串中,请使用bluefeet示例,如果您需要一个记录集,其中包含每种类型的记录:
select
data_type,
max(value) as value
from table1
group by data_type