如何在PostgreSQL的SELECT语句中将行值用作列?
我的PostgreSQL 9.2.8数据库中有一个包含以下三个表的表结构: 我试图找出如何选择一个如何在PostgreSQL的SELECT语句中将行值用作列?,sql,postgresql,postgresql-9.2,Sql,Postgresql,Postgresql 9.2,我的PostgreSQL 9.2.8数据库中有一个包含以下三个表的表结构: 我试图找出如何选择一个orders行,并在同一行上添加order\u points和points中的一些列 您可以将积分表想象为一个人可以购买的所有物品的列表,在该列表中,abbrev内部知道它,并且它的成本金额 order\u points表是购买的每件商品,因此points.id==order\u points.id,和amount类似于他们购买了5块糖果。它通过order\u points.order\u id=
orders
行,并在同一行上添加order\u points
和points
中的一些列
您可以将积分表想象为一个人可以购买的所有物品的列表,在该列表中,abbrev
内部知道它,并且它的成本金额
order\u points
表是购买的每件商品,因此points.id==order\u points.id
,和amount
类似于他们购买了5块糖果。它通过order\u points.order\u id==orders.id
选择订单时,我希望为存在的每个abbrev
以及order\u points
表中的amount
设置一列
因此,如果点
有:
id | name | abbrev | amount
--------------------------------
1 | Snickers | sn | 1.34
2 | Milky Way | mw | 1.73
3 | Coffee | cf | 10.12
id | order_id | points_id | amount
----------------------------------
1 | 1 | 1 | 10
2 | 1 | 3 | 1
而order_points
具有以下特征:
id | name | abbrev | amount
--------------------------------
1 | Snickers | sn | 1.34
2 | Milky Way | mw | 1.73
3 | Coffee | cf | 10.12
id | order_id | points_id | amount
----------------------------------
1 | 1 | 1 | 10
2 | 1 | 3 | 1
然后,当我得到我的行时,我需要订单中的所有列,再加上三个额外的列。我不想列出上面顺序中显示的每一列,但基本上假设我只想要其中的4列,加上所有的点
内容,我最终将其作为一行输出:
id | created | due | name | sn | mw | cf
------------------------------------------------
1 | 2018-04-21 | 2018-05-01 | Fooey | 10 | 0 | 1
我不知道如何从表查找中动态添加具有名称的列(theabbrev
)。您不能动态添加具有未知名称的列。查询中列的名称必须是已知的。但您可以使用一个查询的输出以编程方式定义输出查询中字段的名称。正如Adam Silenko所说,您不能在运行时添加列。您可以做的最好的事情是使用2个查询。一个用于创建包含所需列的临时表的函数,另一个用于查询表并获取结果。这是可以解释的
将创建临时表的函数:
CREATE OR REPLACE FUNCTION get_order(orderId BIGINT)
RETURNS VOID AS
$$
DECLARE column_names varchar[];
DECLARE column_values float[];
DECLARE final_select TEXT := 'SELECT id, name points_columns FROM orders where id=' || orderId;
DECLARE create_table_statement TEXT := 'CREATE TEMP TABLE temp_result_table ON COMMIT DROP AS select_statement';
DECLARE columns_values_concatenated TEXT := '';
BEGIN
SELECT array_agg(abbrev), array_agg(CASE WHEN amount IS NULL THEN 0 ELSE amount END)
into column_names, column_values FROM
(SELECT abbrev, order_points.amount as amount FROM points LEFT JOIN order_points ON points.id = order_points.points_id and order_id = orderId
ORDER BY points.id) points_amount;
FOR i IN 1 .. array_upper(column_names, 1)
LOOP
columns_values_concatenated := columns_values_concatenated || ', ' || column_values[i] || ' as ' || column_names[i];
end loop;
final_select := replace(final_select, 'points_columns',columns_values_concatenated);
create_table_statement:= replace(create_table_statement, 'select_statement', final_select);
EXECUTE create_table_statement;
end;
$$ LANGUAGE Plpgsql;
我们使用两个数组,column\u names
和column\u values
分别存储所选顺序的名称(“sn”、“mw”、“cf”)和这些名称的值
我们使用这两个数组来生成select语句(在当前代码中,我只从orders表中获取id和名称,但您可以轻松地更改它)。我们将select语句存储到final\u select
变量中。最后,我们将生成的select语句添加到create\u table\u语句中,并创建和填充临时表
现在,正如上面链接中所解释的,因为我们需要两个查询来访问数据,所以我们必须在一个事务中执行这两个查询(如果我们多次调用函数,为了避免名称冲突)
您能否向我们展示所需的输出,而不仅仅是您想要的额外列?我在示例中添加了来自orders
的一些列。您可能需要postgres的交叉表功能。这些帖子应该会有帮助:order\u points.point\u id是否唯一?在points
中有多少行?您能否进一步扩展请问?你是说我可以从代码而不仅仅是SQL来做吗?没错。阅读crostab。最好的方法是使用交叉表(文本源代码\u SQL,文本类别\u SQL)
,但您必须知道字段名称crosstab函数声明为返回记录集,因此输出列的实际名称和类型必须在调用SELECT语句的FROM子句中定义,例如:SELECT*FROM crosstab(“…”,“…”)AS ct(row_name text,extra text,cat1 text,cat2 text,cat3 text,cat4 text);
我根本不知道如何用它来解决这个问题。我只写如何解决这个问题,如果你想要一些代码,请提供更多细节……我不知道如何提供比我在问题中所做的更多的细节。