我在PostgreSQL 9.2.8数据库中有这三个表的表结构:
我正在试图找出如何选择订单行,并在SAME行上添加order_points和points中的一些列.
您可以将点表视为一个人可以购买的所有项目的列表,其中内部由缩写和成本金额知道.
order_points表是购买的每件商品,所以points.id == order_points.points_id,金额类似于说他们买了5个糖果棒.它通过order_points.order_id == orders.id链接到订单
当我选择订单时,我希望每个存在的缩写都有一列,以及order_points表中的金额.
所以如果点有这个:
id | name | abbrev | amount -------------------------------- 1 | Snickers | sn | 1.34 2 | Milky Way | mw | 1.73 3 | Coffee | cf | 10.12
和order_points有这个:
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
我不知道如何从表查找中动态添加名称(缩写)的列.
解决方法
正如Adam Silenko所说,您无法在运行时添加列.您可以做的最好的事情是使用2个查询.一个函数将创建一个包含所需列的临时表,另一个函数用于查询表并获取结果.这是解释
here.
将创建临时表的函数:
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;
我们使用2个数组,column_names和column_values来分别存储所选订单的名称(“sn”,“mw”,“cf”)和这些名称的值.
我们使用这两个数组来生成select语句(在当前代码中,我只从orders表中获取id和name,但您可以轻松地更改它).我们将select语句存储到final_select变量中.最后,我们将生成的select语句添加到create_table_statement中,然后创建并填充临时表.
现在,正如上面的链接所解释的那样,因为我们需要2个查询来访问数据,所以我们必须在单个事务中执行两个查询(为了避免名称冲突,如果我们多次调用该函数).
BEGIN; SELECT * FROM get_order(1); SELECT * FROM temp_result_table; COMMIT; --The temporary table will be dropped on commit