Insert into table from select distinct query in postgresql - postgresql

I have a table with 33 columns that has several duplicates so i am trying to remove all the duplicates this way because this select distinct query has the correct number of data.
CREATE TABLE students (
school char(2),sex char(1),age int,address char(1),famsize char(3),
Pstatus char(1),Medu int,Fedu int,Mjob varchar,Fjob varchar,reason varchar,
guardian varchar,traveltime int,studytime int,failures char(1),
schoolsup varchar,famsup varchar,paid varchar,activities varchar,
nursery varchar,higher varchar,internet varchar,romantic varchar,
famrel int,freetime int,goout int,Dalc int,Walc int,
health int,absences int,id serial primary key)
I want to insert all values from this select distinct query
with 8 columns into a different empty table.
SELECT DISTINCT ("school","sex","age","address","famsize","Pstatus","Medu","Fedu","Mjob","Fjob","reason","nursery","internet")
FROM students;

I want to insert all values from this select distinct query with 8 columns into a different empty table.
Use create table .. as select ... if you want to create the table
create table new_table
as
SELECT DISTINCT school, sex, age, address, famsize, "Pstatus", "Medu", "Fedu", "Mjob", "Fjob", reason, nursery, internet
FROM students;
Other wise just use an insert based on a select:
insert into empty_table (school, sex, age, address, famsize, "Pstatus", "Medu", "Fedu", "Mjob", "Fjob", reason, nursery, internet)
SELECT DISTINCT school, sex, age, address, famsize, "Pstatus", "Medu", "Fedu", "Mjob", "Fjob", reason, nursery, internet
FROM students;
Very important: do not put parentheses around the columns in the select list - that creates a single column with an anonymous record type.

insert into destinationTable(dC1, dC2, dC3, dC4, dC5, dC6, dC7, dC8)
select sC1, sC2, sC3, sC4, sC5, sC6, sC7, sC8
from sourceTable
You can join the tables to get the 33 columns.

Related

How to aggregate all numbers of a column in postgresql?

I'm trying to find some of all rows, with the same city name in an specific time. My table is :
CREATE TABLE fp_stores_data_test (
time INTEGER,
city VARCHAR(20),
market_id INTEGER,
product_id INTEGER,
price INTEGER,
has_sold INTEGER,
PRIMARY KEY (time, city, province, market_id ,product_id)
);
I want to create another table which is have time,city and has_sold columns. This one will show how much is sold in this city on that specific time. I don't know how to create this table using my first table. some sample input:
1594809782,city1,0,3588,54000,36
1594809782,city1,0,4813,59000,16
1594809782,city2,0,879,35000,33
1594809782,city2,0,2902,57000,13
1594809786,city1,0,3199,52000,5
1594809786,city1,1,864,35000,32
1594809786,city2,1,5297,37000,14
1594809786,city2,1,5339,40000,19
here, for city1 in time 1594809782 we have two rows. These two row will be one row in the next table. with the same time and city but has_sold values will sum up in.
1594809782,city1,52
1594809782,city2,46
1594809786,city1,37
1594809786,city2,33
I think that this will do exactly what you need:
select time, city, sum(has_sold) has_sold
from fp_stores_data_test
group by time, city
order by time, city;
And you can store the query results in a table like this
select time, city, sum(has_sold) has_sold
into [temporary table] fp_stores_data_agg
from fp_stores_data_test
group by time, city;
[temporary table] is of course optional if you only need the aggregated table during the session and remove it afterwards.

show records that have only one matchin row in another table

I need to write a sql code that probably is very simple but I am very new to it.
I need to find all the records from one table that have matching id (but no more than one) from the other table. eg. one table contains records of the employees and the second one with employees' telephone numbers. i need to find all employees with only one telephone no
Sample data would be nice. In absence of:
SELECT
employees.employee_id
FROM
employees
LEFT JOIN
(SELECT distinct on(employee_id) employee_id FROM emp_phone) AS phone
ON
employees.employee_id = phone.employee_id
WHERE
phone.employee_id IS NOT NULL;
You need a join of the 2 tables, group by employee and the condition in the having clause:
SELECT e.employee_id, e.name
FROM employees e INNER JOIN numbers n
ON e.employee_id = n.employee_id
GROUP BY e.employee_id, e.name
HAVING COUNT(*) = 1;
If there can be more than a few numbers per employee in the table with the employees' telephone numbers (calling it tel), then it's cheaper to avoid GROUP BY and HAVING which has to process all rows. Find employees with "unique" numbers using a self-anti-join with NOT EXISTS.
While you don't need more than the employee_id and their unique phone number, you don't even have to involve the employee table at all:
SELECT *
FROM tel t
WHERE NOT EXISTS (
SELECT FROM tel
WHERE employee_id = t.employee_id
AND tel_number <> t.tel_number -- or use PK column
);
If you need additional columns from the employee table:
SELECT * -- or any columns you need
FROM (
SELECT employee_id AS id, tel_number -- or any columns you need
FROM tel t
WHERE NOT EXISTS (
SELECT FROM tel
WHERE employee_id = t.employee_id
AND tel_number <> t.tel_number -- or use PK column
)
) t
JOIN employee e USING (id);
The column alias in the subquery (employee_id AS id) is just for convenience. Then the outer join condition can be USING (id), and the ID column is only included once in the result, even with SELECT * ...
Simpler with a smart naming convention that uses employee_id for the employee ID everywhere. But it's a widespread anti-pattern to use employee.id instead.
Related:
JOIN table if condition is satisfied, else perform no join

Add Column in table with value partition by group

My table is somethingg like
CREATE TABLE table1
(
_id text,
name text,
data_type int,
data_value int,
data_date timestamp -- insertion time
);
Now due to a system bug, many duplicate entries are created and I need to remove those duplicated and keep only unique entries excluding data_date because it is a system generated date.
My query to do that is something like:
DELETE FROM table1 A
USING ( SELECT _id, name, data_type, data_value, MIN(data_date) min_date
FROM table1
GROUP BY _id, name, data_type, data_value
HAVING count(data_date) > 1) B
WHERE A._id = B._id
AND A.name = B.name
AND A.data_type = B.data_type
AND A.data_value = B.data_value
AND A.data_date != B.min_date;
However this query works, having millions of records in the table, I want a faster way for it. My idea is to create a new column with value as partition by [_id, name, data_type, data_value] or columns which are in group by. However, I could not find the way to create such column.
I would appretiate if any one may suggest a way to create such column.
Edit 1:
There is another thing to add, I don't want to use CTE or subquery for updating this new column because it will be same as my existing query.
The best way is simply creating a new table without duplicated records:
CREATE...
SELECT _id, name, data_type, data_value, MIN(data_date) min_date
FROM table1
GROUP BY _id, name, data_type, data_value;
Alternatively, you can create a rank and then filter, but a subquery is needed.
RANK() OVER (PARTITION BY your_variables ORDER BY data_date ASC) r
And then filter r=1.

Returning rows with distinct column value with data jpa named query

Assuming I have a table with 3 columns, ID, Name, City and I want to use named query to return rows with unique city..can it be done?
Are you asking whether it is possible to write a query that will return the cities that appear in exactly one row, in a table that has ID/Name/City triplets where there could be multiple rows for the same city but with different names?
If so, it would depend on the database engine behind the scenes - but you could try things like:
with candidates (city, num) as (
select city, count(*) from table
group by city
)
select city from candidates where num = 1
Or
select t1.city from table t1
where not exists (
select * from table t2
where t2.city = t1.city and t2.id <> t1.id
)
where table is your table with these triplets.

How can I get a data list as string in Postgres SQL query?

My tables are
create table parents(
id integer,
name text,
parent_childs text);
create table childs(
parent_id integer,
name text);
Data:
insert into parents values (1, 'Mueller');
insert into childs values (1, 'Peter');
insert into childs values (1, 'Hans');
How can I select this data in format:
parent_name childs
------------------------
Mueller Peter, Hans
Bayer Anna, Petra, Max
And I looking for a simple update to write all names from childs from one parents entry in column parents.parent_childs like 'Peter, Hans'.
To update :
string_agg(expression, delimiter) - input values concatenated into a string, separated by delimiter
In your case :-
expression :- childs.name
delimiter :-,
update parents
set parent_childs =t.cname
from(
select parent_id
,string_agg(childs.name,',') cname
from childs group by parent_id
)t
where t.parent_id=parents.id
How can I select this data in format:
parent_name childs
------------------------
Mueller Peter, Hans
Bayer Anna, Petra, Max
Try this :
select parents.name as parent_name
,string_agg(childs.name,',') childs
from childs
inner join parents on childs.parent_id=parents.id
group by parent_id,parents.name