Show query result column types (PostgreSQL) - postgresql

Is there a way to easily get the column types of a query result? I read the psql documentation, but I don't think it supports that. Ideally, I'd be able to get something like:
columna : text | columnb : integer
----------------+-------------------
oh hai | 42
Is there a way I can get this information without coding something up?

It is possible to get any SELECT query result column type.
Example
Given the following query and result, let's answer the question *"What is the column type of all_ids?"*
SELECT array_agg(distinct "id") "all_ids" FROM "auth_user";
all_ids
--------------------------------------------
{30,461577687337538580,471090357619135524}
(1 row)
We need a mechanism to unveil the type of "all_ids".
On the postgres mailing list archives I found reference to a native pg function called pg_typeof.
Example usage:
SELECT pg_typeof(array_agg(distinct "id")) "all_ids" FROM "auth_user";
Output:
all_ids
----------
bigint[]
(1 row)
Cheers!

It is definitely possible with \gdesc command(psql 11):
\gdesc
Shows the description (that is, the column names and data types) of the result of the current query buffer. The query is not actually
executed; however, if it contains some type of syntax error, that
error will be reported in the normal way.
If the current query buffer is empty, the most recently sent query is described instead.
For example:
$ SELECT * FROM pg_database \gdesc
COLUMN | TYPE
---------------+-----------
datname | name
datdba | oid
encoding | INTEGER
datcollate | name
datctype | name
datistemplate | BOOLEAN
datallowconn | BOOLEAN
datconnlimit | INTEGER
datlastsysoid | oid
datfrozenxid | xid
datminmxid | xid
dattablespace | oid
datacl | aclitem[]

I don't think you can print exactly what you have in the sample, unless you write a stored procedure for it.
One way to do it (two "selects"):
create table my_table as select ...
\d my_table
select * from my_table

Related

Convert comma-separated fields to concat() function

I have a table_product that contains comma-separated strings;
id | products
-----------
1 | tv,phone,tablet
2 | computer,tv
3 | printer,tablet,radio
To avoid manual concatenation, like concat(tv,',',phone,',',tablet)
I want to select the data from table_product.products as concat() statement.
Tried this, but getting an error:
select concat(select products from table_product where id=1) from table_sales
Is there any short and basic way to perform this query?

PostgreSQL convert varchar to numeric and get average

I have a column that I want to get an average of, the column is varchar(200). I keep getting this error. How do I convert the column to numeric and get an average of it.
Values in the column look like
16,000.00
15,000.00
16,000.00 etc
When I execute
select CAST((COALESCE( bonus,'0')) AS numeric)
from tableone
... I get
ERROR: invalid input syntax for type numeric:
The standard way to represent (as text) a numeric in SQL is something like:
16000.00
15000.00
16000.00
So, your commas in the text are hurting you.
The most sensible way to solve this problem would be to store the data just as a numeric instead of using a string (text, varchar, character) type, as already suggested by a_horse_with_no_name.
However, assuming this is done for a good reason, such as you inherited a design you cannot change, one possibility is to get rid of all the characters which are not a (minus sign, digit, period) before casting to numeric:
Let's assume this is your input data
CREATE TABLE tableone
(
bonus text
) ;
INSERT INTO tableone(bonus)
VALUES
('16,000.00'),
('15,000.00'),
('16,000.00'),
('something strange 25'),
('why do you actually use a "text" column if you could just define it as numeric(15,0)?'),
(NULL) ;
You can remove all the straneous chars with a regexp_replace and the proper regular expression ([^-0-9.]), and do it globally:
SELECT
CAST(
COALESCE(
NULLIF(
regexp_replace(bonus, '[^-0-9.]+', '', 'g'),
''),
'0')
AS numeric)
FROM
tableone ;
| coalesce |
| -------: |
| 16000.00 |
| 15000.00 |
| 16000.00 |
| 25 |
| 150 |
| 0 |
See what happens to the 15,0 (this may NOT be what you want).
Check everything at dbfiddle here
I'm going to go out on a limb and say that it might be because you have Empty strings rather than nulls in your column; this would result in the error you are seeing. Try wrapping the column name in a nullif:
SELECT CAST(coalesce(NULLIF(bonus, ''), '0') AS integer) as new_field
But I would really question your schema that you have numeric values stored in a varchar column...

Change column name from aggregate function default postgresql

I created a (big) table like so:
create table names_and_pics as (
select e.emp_name, e.dept, max(p.prof_pic)
from e.employees
left join profiles p
on e.emp_id = p.emp_id )
select * from names_and_pics;
emp_name | dept | max(p.prof_pic)
Dan | IT | 1234.img
Phil | HR | 3344.img
...
Because I forgot to give the 3rd field a name, I need to rename it now to "img_link" The syntax I've been trying is
alter table names_and_pics rename max(p.prof_pic) to img_link;
That gives the following error:
Syntax Error at or near "("
Any ideas how to fix this?
You need to put the column names in double quotes because it contains invalid characters:
alter table names_and_pics rename "max(p.prof_pic)" to img_link;
More about quoted identifiers in the manual
http://www.postgresql.org/docs/current/static/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS
Btw: the parentheses around the select in your create table ... as select statement are useless noise

Is it possible in PL/pgSQL to evaluate a string as an expression, not a statement?

I have two database tables:
# \d table_1
Table "public.table_1"
Column | Type | Modifiers
------------+---------+-----------
id | integer |
value | integer |
date_one | date |
date_two | date |
date_three | date |
# \d table_2
Table "public.table_2"
Column | Type | Modifiers
------------+---------+-----------
id | integer |
table_1_id | integer |
selector | text |
The values in table_2.selector can be one of one, two, or three, and are used to select one of the date columns in table_1.
My first implementation used a CASE:
SELECT value
FROM table_1
INNER JOIN table_2 ON table_2.table_1_id = table_1.id
WHERE CASE table_2.selector
WHEN 'one' THEN
table_1.date_one
WHEN 'two' THEN
table_1.date_two
WHEN 'three' THEN
table_1.date_three
ELSE
table_1.date_one
END BETWEEN ? AND ?
The values for selector are such that I could identify the column of interest as eval(date_#{table_2.selector}), if PL/pgSQL allows evaluation of strings as expressions.
The closest I've been able to find is EXECUTE string, which evaluates entire statements. Is there a way to evaluate expressions?
In the plpgsql function you can dynamically create any expression. This does not apply, however, in the case you described. The query must be explicitly defined before it is executed, while the choice of the field occurs while the query is executed.
Your query is the best approach. You may try to use a function, but it will not bring any benefits as the essence of the issue will remain unchanged.

How to query PostgreSQL as list of column name and value instead of table [duplicate]

This question already has answers here:
Display select results vertically in psql, as is done by MySQL's \G
(2 answers)
Closed 7 years ago.
in MySQL I could display query result as a list, for example:
id : 123
name : 'test'
foo : 'bar'
instead of standard result:
+----+------+-----+
| id | name | foo |
+----+------+-----+
| 123|test |bar |
+----+------+-----+
using select * from tablename \G in mysql command line.
How to do this in PostgreSQL's psql?
I think you might be looking for the expanded output \x.
regress=> \x
Expanded display is on.
regress=> select * from posts;
-[ RECORD 1 ]---------
id | 1
title | bork bork bork
-[ RECORD 2 ]---------
id | 2
title | honkey tonk
or maybe \x\t\a (extended, tuples-only, unaligned):
craig=> \x\t\a
Expanded display is on.
Tuples only is on.
Output format is unaligned.
craig=> select * from posts;
id|1
title|bork bork bork
id|2
title|honkey tonk
You may want \f : too:
craig=> \x\t\a\f :
Expanded display is on.
Tuples only is on.
Output format is unaligned.
Field separator is ":".
craig=> select * from posts;
id:1
title:bork bork bork
id:2
title:honkey tonk
When I'm invoking psql from a script, I tend to use:
psql -qAt
often with the -0 option, too, so it emits null bytes as record separators so fields with embedded newlines are more easily handled.