Change column name from aggregate function default postgresql - 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

Related

PSQL - UPDATE tableA off tableB where Column1 Match

I have a broken column with null values, however I have managed to import the data off a csv into TempTable
MediaRecords - localpath column is null
TempTable - localpath column is correct
UPDATE mediarecords
SET localpath = TempTable.localpath
FROM TempTable
WHERE recordid = TempTable.recordid;
I keep getting ERROR: relation "temptable" does not exist
LINE 3: FROM TempTable
however I can browse the table and see the data.
I tried following this How to update selected rows with values from a CSV file in Postgres? and here we are
Hu Bucky, can you check how the table is actually called because I see you referring at it as TempTable with camelcase and the error states temptable all lowercase.
PostgreSQL could be case sensitive. As example if you do the following
create table "TempTableABC" (id int);
Trying to select from temptableABC will fail
defaultdb=> select * from temptableABC;
ERROR: relation "temptableabc" does not exist
LINE 1: select * from temptableABC;
^
You'll need to use the same quoted syntax to make it work
defaultdb=> select * from "TempTableABC";
id
----
(0 rows)
UPDATE mediarecords
SET localpath = "TempTable".localpath
FROM public."TempTable"
WHERE "mediarecords".recordid = "TempTable".recordid;
Worked

Find duplicate rows by field using typeorm

I'm using typeorm with Postgres.
Having a table with columns (id, name), I want to find all names that are duplicate in the table
E.g. If I have:
id | name
1 | Foo
2 | Bar
3 | Foo
4 | Arthur
I want to get Foo
In SQL I usually do the following:
SELECT name FROM my_table GROUP BY name HAVING COUNT(name) > 1;
However, I'm not sure how to write the same query (or similar) with typeorm.
You can do the same thing but in where part.
getConnection().getRepository(MyTable)
.createQueryBuilder('my_table')
.select('my_table.name')
.groupBy('my_table.name')
.where('COUNT(my_table.name) > 1')
.getRawMany();

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...

Show query result column types (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

Postgres query error

I have a query in postgres
insert into c_d (select * from cd where ak = '22019763');
And I get the following error
ERROR: column "region" is of type integer but expression is of type character varying
HINT: You will need to rewrite or cast the expression.
An INSERT INTO table1 SELECT * FROM table2 depends entirely on order of the columns, which is part of the table definition. It will line each column of table1 up with the column of table2 with the same order value, regardless of names.
The problem you have here is whatever column from cd with the same order value as c_d of the table "region" has an incompatible type, and an implicit typecast is not available to clear the confusion.
INSERT INTO SELECT * statements are stylistically bad form unless the two tables are defined, and will forever be defined, exactly the same way. All it takes is for a single extra column to get added to cd, and you'll start getting errors about extraneous extra columns.
If it is at all possible, what I would suggest is explicitly calling out the columns within the SELECT statement. You can call a function to change type within each of the column references (or you could define a new type cast to do this implicitly -- see CREATE CAST), and you can use AS to set the column label to match that of your target column.
If you can't do this for some reason, indicate that in your question.
Check out the PostgreSQL insert documentation. The syntax is:
INSERT INTO table [ ( column [, ...] ) ]
{ DEFAULT VALUES | VALUES ( { expression | DEFAULT } [, ...] ) | query }
which here would look something like:
INSERT INTO c_d (column1, column2...) select * from cd where ak = '22019763'
This is the syntax you want to use when inserting values from one table to another where the column types and order are not exactly the same.