如何从一列中 select 元素并在结果中将它们显示为 headers?
How to select elements from one column and display them as headers in result?
假设 PostgreSQL table 结构如下所示:
Time | Name | Value
w | d | 0
x | a | 1
x | b | 2
y | c | 3
y | b | 4
z | c | 5
z | a | 6
z | d | 7
我有显示数据的需求如下:
Time | Name A | Name B | Name C |
x | 1 | 2 | |
y | | 4 | 3 |
z | 6 | | 5 |
Name 变量的数量在查询之前未定义且未知,唯一完成的过滤是按时间进行的。 table 的行数达到数百万,时间至关重要。换句话说,用户在请求时能够动态地 select Name 变量 he/she 希望在结果中看到显示以及要过滤的时间范围。
我目前实施的方法在收到请求时在 real-time 中生成一个动态查询,如下所示:
WITH SubQuery AS(
SELECT "Name", "Time", "Value"
FROM "Table"
WHERE "Name" IN ('a','b','c') AND "Time" BETWEEN 'x' AND 'z'
ORDER BY "Time" ASC
)
SELECT ("MasterTime") as "Time", "Name A","Name B","Name C"
FROM (
SELECT "Time" as "MasterTime"
FROM SubQuery
) AS "TimeData" FULL OUTER JOIN (
SELECT "Time" as "Time'A'", "Value" as "Name A"
FROM SubQuery WHERE "Name" = 'a'
) AS "Data'A'" ON "MasterTime"="Time'A'" FULL OUTER JOIN (
SELECT "Time" as "Time'B'", "Value" as "Name B"
FROM SubQuery WHERE "Name" = 'b'
) AS "Data'B'" ON "MasterTime"="Time'B'" FULL OUTER JOIN (
SELECT "Time" as "Time'C'", "Value" as "Name C"
FROM SubQuery WHERE "Name" = 'c'
) AS "Data'C'" ON "MasterTime"="Time'C'"
ORDER BY "MasterTime" ASC
我在想这可能是数据库世界中的一个常见问题,可能有更好的解决方案。欢迎所有建议。
SQL 在解析和准备查询后无法增加列数。您不能根据它在执行期间发现的不同值来显示更多列。这意味着您需要在设计查询时对列进行硬编码。
SELECT "Time",
COALESCE(MAX(CASE "Name" WHEN 'a' THEN "Value" END), '') AS "Name A",
COALESCE(MAX(CASE "Name" WHEN 'b' THEN "Value" END), '') AS "Name B",
COALESCE(MAX(CASE "Name" WHEN 'c' THEN "Value" END), '') AS "Name C"
FROM "Table"
WHERE "Name" IN ('a','b','c') AND "Time" BETWEEN 'x' AND 'z'
GROUP BY "Time"
ORDER BY "Time" ASC;
CTE 子查询是不必要的,也没有帮助。
另一种解决问题的方法是
SELECT time, a as name_a, b as name_b, c as name_c
FROM
(
SELECT time,name,value
FROM table1
) s
PIVOT
(
MAX(Value) FOR name IN (a,b,c)
) p
假设 PostgreSQL table 结构如下所示:
Time | Name | Value
w | d | 0
x | a | 1
x | b | 2
y | c | 3
y | b | 4
z | c | 5
z | a | 6
z | d | 7
我有显示数据的需求如下:
Time | Name A | Name B | Name C |
x | 1 | 2 | |
y | | 4 | 3 |
z | 6 | | 5 |
Name 变量的数量在查询之前未定义且未知,唯一完成的过滤是按时间进行的。 table 的行数达到数百万,时间至关重要。换句话说,用户在请求时能够动态地 select Name 变量 he/she 希望在结果中看到显示以及要过滤的时间范围。
我目前实施的方法在收到请求时在 real-time 中生成一个动态查询,如下所示:
WITH SubQuery AS(
SELECT "Name", "Time", "Value"
FROM "Table"
WHERE "Name" IN ('a','b','c') AND "Time" BETWEEN 'x' AND 'z'
ORDER BY "Time" ASC
)
SELECT ("MasterTime") as "Time", "Name A","Name B","Name C"
FROM (
SELECT "Time" as "MasterTime"
FROM SubQuery
) AS "TimeData" FULL OUTER JOIN (
SELECT "Time" as "Time'A'", "Value" as "Name A"
FROM SubQuery WHERE "Name" = 'a'
) AS "Data'A'" ON "MasterTime"="Time'A'" FULL OUTER JOIN (
SELECT "Time" as "Time'B'", "Value" as "Name B"
FROM SubQuery WHERE "Name" = 'b'
) AS "Data'B'" ON "MasterTime"="Time'B'" FULL OUTER JOIN (
SELECT "Time" as "Time'C'", "Value" as "Name C"
FROM SubQuery WHERE "Name" = 'c'
) AS "Data'C'" ON "MasterTime"="Time'C'"
ORDER BY "MasterTime" ASC
我在想这可能是数据库世界中的一个常见问题,可能有更好的解决方案。欢迎所有建议。
SQL 在解析和准备查询后无法增加列数。您不能根据它在执行期间发现的不同值来显示更多列。这意味着您需要在设计查询时对列进行硬编码。
SELECT "Time",
COALESCE(MAX(CASE "Name" WHEN 'a' THEN "Value" END), '') AS "Name A",
COALESCE(MAX(CASE "Name" WHEN 'b' THEN "Value" END), '') AS "Name B",
COALESCE(MAX(CASE "Name" WHEN 'c' THEN "Value" END), '') AS "Name C"
FROM "Table"
WHERE "Name" IN ('a','b','c') AND "Time" BETWEEN 'x' AND 'z'
GROUP BY "Time"
ORDER BY "Time" ASC;
CTE 子查询是不必要的,也没有帮助。
另一种解决问题的方法是
SELECT time, a as name_a, b as name_b, c as name_c
FROM
(
SELECT time,name,value
FROM table1
) s
PIVOT
(
MAX(Value) FOR name IN (a,b,c)
) p