2012-04-10 44 views
3

我有像下面的查询,它没有列的PostgreSQL行字符串

ID COL1 COL2 COL3 COL4 
------------------------------------- 
1 VAL11 VAL12 VAL13 VAL14 
2 VAL21 VAL22 VAL23 VAL24 

固定数量的结果现在我想的结果是这样的。

RESULT 
----------------------------------------------------- 
ID:1, COL1:VAL11, COL2:VAL12, COL3:VAL13, COL4:VAL14 
ID:2, COL1:VAL21, COL2:VAL22, COL3:VAL23, COL4:VAL24 

请帮忙。

回答

3

快速和肮脏的方式,但没有列名和包括NULL值:

SELECT tbl::text 
FROM tbl; 

缓慢&法子:

SELECT array_to_string(ARRAY[ 
      'ID:' || id 
     ,'COL1:' || col1 
     ,'COL2:' || col2 
     ], ', ') AS result 
FROM tbl; 

如果列包含NULL值,它会在结果中失踪。我不只是连接,因为NULL值会使整行无效。
array_to_string()确保只在需要的地方插入逗号。


PostgreSQL的9.1引入的新功能concat_ws()(很像一个在MySQL),使我们可以进一步简化:

SELECT concat_ws(', ' 
      'ID:' || id 
     ,'COL1:' || col1 
     ,'COL2:' || col2 
     ) AS result 
FROM tbl; 
+2

通过简单地连接值而不是先创建一个数组,然后再将该数组转换回字符串,第二种方式更容易吗? – 2012-04-10 15:38:11

+1

@a_horse_with_no_name:那么如何处理NULL值?您需要为每个列添加一个“CASE”语句,并且很难使逗号合适。去过也做过。这种方式更容易。如果没有NULL值,你会是对的。 – 2012-04-10 15:40:11

+0

好点。没有想到NULL值。 – 2012-04-10 16:33:29

1
SELECT 
      'ID:' ||coalesce(id::text, '<null>') 
    ||', '||'COL1:'||coalesce(col1::text, '<null>') 
    ||', '||'COL2:'||coalesce(col2::text, '<null>') 
FROM tbl; 

您可以使用此SQL生成第一一个给你(如果有很多列的话):

SELECT E'SELECT \n'||string_agg(trim(stmt), E' \n')||E'\n FROM tbl;' 
    FROM (SELECT 
    CASE WHEN a.attnum > 1 THEN $$||', '||$$ ELSE '' END || 
    $$'$$||upper(a.attname)||$$:'||coalesce($$||quote_ident(a.attname)|| 
    $$::text, '<null>')$$ AS stmt 
    FROM pg_attribute a, pg_class t 
WHERE t.relkind='r' AND t.relname = 'tbl' AND a.attrelid = t.oid 
    AND NOT a.attisdropped AND a.attnum > 0) AS s; 
+0

如果用NULL代替占位符列,则变得更简单。棘手的部分是修剪NULL列。假设第一列是NULL,或者是第一个和第二个列......从pg 9.1开始,你可以用'concat_ws()'进一步简化。 – 2012-04-10 20:35:49