error while trying to name column in select query [duplicate] - postgresql

I encountered a strange issue this morning. I was creating a view simplifying a list of applications in a Postgres table.
This failed.
CREATE OR REPLACE VIEW application_view AS
SELECT COALESCE( nullif(full_name,''), nullif(additional_info,''), app_name) name
, id
FROM application
ORDER BY COALESCE( nullif(full_name,''), nullif(additional_info,''), app_name)
whereas
CREATE OR REPLACE VIEW application_view AS
SELECT COALESCE( nullif(full_name,''), nullif(additional_info,''), app_name) application
, id
FROM application
ORDER BY COALESCE( nullif(full_name,''), nullif(additional_info,''), app_name)
worked.
I often use name as a column name in tables so any ideas as to why the first sql statement failed?

It's a keyword. When you want to use a keyword as an alias in the select list you have to use the word as:
select 1 name;
ERROR: syntax error at or near "name"
LINE 1: select 1 name;
select 1 as name;
name
------
1
(1 row)
From the documentation about aliases in the select list:
To specify the name to use for an output column, write AS output_name after the column's expression. (You can omit AS, but only if the desired output name does not match any PostgreSQL keyword (see Appendix C). For protection against possible future keyword additions, it is recommended that you always either write AS or double-quote the output name.)

Related

"select ;" why does this statement exist in postgresql

The query:
select ;
is valid in postgresql. It returns a tuple with no attribute.
# select ;
--
(1 row)
It has clear semantics and the result can be used as a subquery:
# select 1 from (select ) as rip;
?column?
----------
1
(1 row)
In fact, one can create a table with no attributes using it. One can even add tuples to it!!
But my question is, why does it exist?
I see value in a select without a from clause, as psql can be used as a calculator:
# select 3 * 6;
?column?
----------
18
(1 row)
and or be used to call a UDF.
But I can not envision a use for select ;
it is useful or is it an oddity of postgresql's parser?
See here:
https://www.postgresql.org/docs/current/sql-select.html
Empty SELECT Lists
The list of output expressions after SELECT can be empty, producing a zero-column result table. This is not valid syntax according to the SQL standard. PostgreSQL allows it to be consistent with allowing zero-column tables. However, an empty list is not allowed when DISTINCT is used.

postgres: apply aggregate function to column with spaces in name

I am trying to run a query like this
SELECT group, sum("a column with spaces") FROM x GROUP BY group
Unfortunately, I get the error function sum(text) does not exist. It appears to be interpreting my quoted identifier "a column with spaces" as a text string instead of column name. How can I specify that this is an identifier?
I found a way to trick it into parsing it as an identifier -- prefix it with the table identifier or alias:
SELECT group, sum(t."a column with spaces") FROM table_name t GROUP BY group;
Double-quotes are actually the right way to identify columns, but in this case it won't work.
I managed to apply an aggregate function renaming the column and removing its white spaces.
CREATE TABLE example (
"column with space" INTEGER
);
INSERT INTO example VALUES (1), (2);
SELECT SUM(column_with_space)
FROM (
SELECT "column with space" AS column_with_space
FROM example
) AS example_query;
Got result:
sum
3

DISTINCT ON (col) col_alias – alias not working

I am trying to run this command:
SELECT DISTINCT ON (_id) test FROM creator_map.infos;
which is giving me the error:
ERROR: column "test" does not exist
but according to the following tutorial, the test should be an alias
SELECT
DISTINCT ON
(column_1) column_1_alias,
column_2
FROM
tbl_name
ORDER BY
column_1,
column_2;
Source.
How do I get the distinct to become an alias?
You can't give on (...) an alias because it's not expression that "returns" a name. It's like trying to give an IN condition an alias where a in (1,2,3) as foo
If in doubt, read the manual. It does not mention an alias there.
You can only define an alias for an expression in the actual select list, and the (...) is not part of the select list, but part of the distinct on expression.
I think it's just a matter of bad wording on that tutorial page, and should read:
select distinct on (column1)
column1 as column_1_alias,
column2
from ....

Can I use a Postgres keyword as an alias in select list?

I encountered a strange issue this morning. I was creating a view simplifying a list of applications in a Postgres table.
This failed.
CREATE OR REPLACE VIEW application_view AS
SELECT COALESCE( nullif(full_name,''), nullif(additional_info,''), app_name) name
, id
FROM application
ORDER BY COALESCE( nullif(full_name,''), nullif(additional_info,''), app_name)
whereas
CREATE OR REPLACE VIEW application_view AS
SELECT COALESCE( nullif(full_name,''), nullif(additional_info,''), app_name) application
, id
FROM application
ORDER BY COALESCE( nullif(full_name,''), nullif(additional_info,''), app_name)
worked.
I often use name as a column name in tables so any ideas as to why the first sql statement failed?
It's a keyword. When you want to use a keyword as an alias in the select list you have to use the word as:
select 1 name;
ERROR: syntax error at or near "name"
LINE 1: select 1 name;
select 1 as name;
name
------
1
(1 row)
From the documentation about aliases in the select list:
To specify the name to use for an output column, write AS output_name after the column's expression. (You can omit AS, but only if the desired output name does not match any PostgreSQL keyword (see Appendix C). For protection against possible future keyword additions, it is recommended that you always either write AS or double-quote the output name.)

Display colon separated values in postgres

I am using postgresql 8.1 and i dont have the new functions in that version. Please help me what to do in that case?
My first table is as follows
unit_office table:
Mandal_ids Name
82:05: test sample
08:20:16: test sample
Mandal Master table:
mandal_id mandal_name
08 Etcherla
16 Hiramandalam
20 Gara
Now when I say select * from unit_office it should display:
Mandal Name of office
Hiramandalam, Gara test sample
i.e in place of ids I want the corresponding names (which are in master table)separated by comma
I have a column in postgres which has colon separated ids. The following is one record from my table.
mandalid
18:82:14:11:08:05:20:16:83:37:23:36:15:06:38:33:26:30:22:04:03:
When I say select * from table, the mandalid column should display the names of the mandals in the id place separated by a comma.
Now i have the corresponding name for the id in a master table.
I want to display the names of the ids in the select query of the first table. like
my first table name is unit office. when i say select * from unit office, I want the names in the place of ids.
I suggest you redesign your tables, but if you cannot, then you may need to define a function, which will split the mandal_ids string into integers, and map them to names. I suggest you read the PostgreSQL documentation on creating functions. The "PL/pgSQL" language may be a good choice. You may use the functions string_to_array and array_to_string.
But if you can, I suggest you define your tables in the following way:
mandals:
id name
16 Hiramandalam
20 Gara
unit_offices:
id name
1 test sample
mandals_in_offices:
office_id mandal_id
1 16
1 20
The output from the following query should be what you need:
SELECT string_agg(m.name,',') AS mandal_names,
max(o.name) AS office_name
FROM mandals_in_offices i
INNER JOIN unit_offices o ON i.office_id = o.id
INNER JOIN mandals m ON i.mandal_id = m.id
GROUP BY o.id;
The function string_agg appeared in PostgreSQL version 9, so if you are using older version, you may need to write similar function yourself. I believe this will not be too hard.
Here's what we did in LedgerSMB:
created a function to do the concatenation
created a custom aggregate to do the aggregation.
This allows you to do this easily.
CREATE OR REPLACE FUNCTION concat_colon(TEXT, TEXT) returns TEXT as
$$
select CASE WHEN $1 IS NULL THEN $2 ELSE $1 || ':' || $2 END;
$$ language sql;
CREATE AGGREGATE concat_colon (
BASETYPE = text,
STYPE = text,
SFUNC = concat_colon
);
Then you can:
select concat_colon(mycol::text) from mytable;
Works just fine.