假设PostgreSQL表结构如下所示:
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变量的数量是未定义和未知的,唯一的过滤是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
我认为这可能是数据基础领域的一个常见问题,可能还有更好的解决方案。欢迎提出所有建议。
答案 0 :(得分:1)
在解析和准备查询后,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子查询是不必要的,并没有帮助。
答案 1 :(得分:0)
另一种解决问题的方法是
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