Return 列名称和不同的值
Return column name and distinct values
假设我在 postgres 中有一个简单的 table,如下所示:
+--------+--------+----------+
| Car | Pet | Name |
+--------+--------+----------+
| BMW | Dog | Sam |
| Honda | Cat | Mary |
| Toyota | Dog | Sam |
| ... | ... | ... |
我想 运行 一个 sql 查询,该查询可以 return 第一列中的列名和第二列中的唯一值。例如:
+--------+--------+
| Col | Vals |
+--------+--------+
| Car | BMW |
| Car | Toyota |
| Car | Honda |
| Pet | Dog |
| Pet | Cat |
| Name | Sam |
| Name | Mary |
| ... | ... |
-- Query 4b. (104 ms, 128 ms)
select distinct unnest( array_agg(a)||
array_agg(b)||
array_agg(c)||
array_agg(d) )
from t ;
但是我对代码的理解不够深入,不知道如何将列名附加到另一列中。
I also found a query that can return the column names in a table. 也许这个子查询与上面显示的 "Query 4b" 相结合?
SELECT distinct
unnest(array['car', 'pet', 'name']) AS col,
unnest(array[car, pet, name]) AS vals
FROM t
order by col
与JSON functions
row_to_json()
和 json_each_text()
你可以不指定列的数量和名称:
select distinct key as col, value as vals
from (
select row_to_json(t) r
from a_table t
) t,
json_each_text(r)
order by 1, 2;
将返回集合的函数放在 SELECT
列表中是一种糟糕的风格,并且在 SQL 标准中是不允许的。 Postgres 出于历史原因支持它,但自从 LATERAL
引入 Postgres 9.3 以来,它基本上已过时。我们也可以在这里使用它:
SELECT x.col, x.val
FROM tbl, LATERAL (VALUES ('car', car)
, ('pet', pet)
, ('name', name)) x(col, val)
GROUP BY 1, 2
ORDER BY 1, 2;
您会在 the very same question on dba.SE you already found yourself 下找到此 LATERAL (VALUES ...)
技术的讨论。不要看到第一个答案就停止阅读。
直到 Postgres 9.4 仍然存在一个例外:"parallel unnest" 需要在 SELECT
列表中组合多个集合返回函数。 Postgres 9.4 也带来了 new variant of unnest()
来消除这种必要性。更多:
如果 SELECT 列表中所有返回集合的函数的返回行数不完全相同,则新函数也不会偏离笛卡尔积,这是(曾经)非常奇怪的行为。新的语法变体应该优于现在已经过时的语法变体:
SELECT DISTINCT x.*
FROM tbl t, unnest('{car, pet, name}'::text[]
, ARRAY[t.car, t.pet, t.name]) AS x(col, val)
ORDER BY 1, 2;
也比两个 unnest()
并行调用更短更快。
Returns:
col | val
------+--------
car | BMW
car | Honda
car | Toyota
name | Mary
name | Sam
pet | Cat
pet | Dog
DISTINCT
或 GROUP BY
,两者都适合任务。
假设我在 postgres 中有一个简单的 table,如下所示:
+--------+--------+----------+
| Car | Pet | Name |
+--------+--------+----------+
| BMW | Dog | Sam |
| Honda | Cat | Mary |
| Toyota | Dog | Sam |
| ... | ... | ... |
我想 运行 一个 sql 查询,该查询可以 return 第一列中的列名和第二列中的唯一值。例如:
+--------+--------+
| Col | Vals |
+--------+--------+
| Car | BMW |
| Car | Toyota |
| Car | Honda |
| Pet | Dog |
| Pet | Cat |
| Name | Sam |
| Name | Mary |
| ... | ... |
-- Query 4b. (104 ms, 128 ms)
select distinct unnest( array_agg(a)||
array_agg(b)||
array_agg(c)||
array_agg(d) )
from t ;
但是我对代码的理解不够深入,不知道如何将列名附加到另一列中。
I also found a query that can return the column names in a table. 也许这个子查询与上面显示的 "Query 4b" 相结合?
SELECT distinct
unnest(array['car', 'pet', 'name']) AS col,
unnest(array[car, pet, name]) AS vals
FROM t
order by col
与JSON functions
row_to_json()
和 json_each_text()
你可以不指定列的数量和名称:
select distinct key as col, value as vals
from (
select row_to_json(t) r
from a_table t
) t,
json_each_text(r)
order by 1, 2;
将返回集合的函数放在 SELECT
列表中是一种糟糕的风格,并且在 SQL 标准中是不允许的。 Postgres 出于历史原因支持它,但自从 LATERAL
引入 Postgres 9.3 以来,它基本上已过时。我们也可以在这里使用它:
SELECT x.col, x.val
FROM tbl, LATERAL (VALUES ('car', car)
, ('pet', pet)
, ('name', name)) x(col, val)
GROUP BY 1, 2
ORDER BY 1, 2;
您会在 the very same question on dba.SE you already found yourself 下找到此 LATERAL (VALUES ...)
技术的讨论。不要看到第一个答案就停止阅读。
直到 Postgres 9.4 仍然存在一个例外:"parallel unnest" 需要在 SELECT
列表中组合多个集合返回函数。 Postgres 9.4 也带来了 new variant of unnest()
来消除这种必要性。更多:
如果 SELECT 列表中所有返回集合的函数的返回行数不完全相同,则新函数也不会偏离笛卡尔积,这是(曾经)非常奇怪的行为。新的语法变体应该优于现在已经过时的语法变体:
SELECT DISTINCT x.*
FROM tbl t, unnest('{car, pet, name}'::text[]
, ARRAY[t.car, t.pet, t.name]) AS x(col, val)
ORDER BY 1, 2;
也比两个 unnest()
并行调用更短更快。
Returns:
col | val
------+--------
car | BMW
car | Honda
car | Toyota
name | Mary
name | Sam
pet | Cat
pet | Dog
DISTINCT
或 GROUP BY
,两者都适合任务。