Delete duplicate rows with Active flag false in Postgresql - postgresql

I have a table with columns "ID", "Name" , "Email" , "Active". I added some duplicate values to the table.
I want to delete duplicate rows with flag false not all rows with active flag false. In the table I want to delete 2nd row only.

You may try below co-related sub-query (Before actual delete, You might want to to see the result using SELECT query)-
DELETE FROM YOUR_TABLE T1
WHERE EXISTS (SELECT NULL
FROM YOUR_TABLE T2
WHERE T1.ID = T2.ID
AND T1.NAME = T2.NAME
AND T1.EMAIL = T2.EMAIL
AND T1.ACTIVE <> T2.ACTIVE)
AND UPPER(T1.ACTIVE) = 'FALSE'

Try the below query:
DELETE t1 FROM tablename t1
INNER JOIN tablename t2
WHERE t1.id > t2.id AND t1.Name = t2.Name AND t1.Email =t2.Email AND t1.Active='FALSE'

DELETE FROM users T1
USING users T2
WHERE T1.ID <> T2.ID
AND T1.Name = T2.Name
AND T1.Email = T2.Email
AND T1.Active = FALSE;
DEMO
CREATE TABLE IF NOT EXISTS users (
ID serial PRIMARY KEY,
Name VARCHAR ( 50 ) NOT NULL,
Email VARCHAR ( 50 ) NOT NULL,
Active BOOLEAN NOT NULL
);
INSERT INTO users(Name, Email, Active) VALUES
('John', 'john.gmail.com', TRUE),
('John', 'john.gmail.com', FALSE),
('Bob', 'bob.gmail.com', FALSE);
SELECT * FROM users;
DELETE FROM users T1
USING users T2
WHERE T1.ID <> T2.ID
AND T1.Name = T2.Name
AND T1.Email = T2.Email
AND T1.Active = FALSE;
SELECT * FROM users;

DELETE FROM some_table
WHERE id IN (SELECT id FROM some_table GROUP BY id HAVING COUNT(*)>1)
AND NOT active;

Related

Does Redshift support User-Defined Variables in SELECT?

I'm reviewing some of our Redshift queries and found cases with multiple levels of nested select like the one below:
LEFT JOIN
(
SELECT *
FROM (
SELECT
id,
created_at,
min(created_at) OVER (PARTITION BY id, slug) AS transition_date
FROM table
WHERE status = 'cancelled'
GROUP BY id, Y, Z, created_at
)
WHERE created_at = transition_date
) t1 ON b.id = t1.id
if this were MySQL, I would've done something like this to remove one level of nested select:
LEFT JOIN
(
SELECT
id,
created_at,
#tdate := min(created_at) OVER (PARTITION BY id, slug) AS transition_date
FROM table
WHERE status = 'cancelled' and #tdate = bul.created_at
GROUP BY id, Y, Z, created_at
) t1 ON b.id = t1.id
Is it possible to so something similar in RedShift?
--- update
forgot to include GROUP BY in the nested SELECT, which may affect the answer
You can move the condition for the transition_date into the JOIN condition:
LEFT JOIN
(
SELECT
id,
created_at,
min(created_at) OVER (PARTITION BY id, slug) AS transition_date
FROM table
WHERE status = 'cancelled'
) t1 ON b.id = t1.id AND t1.created_at = t1.transition_date

postgresql 9.5.7: INSERT WHERE NOT IN (or NOT EXISTS) not working with bulk-insert of multiple lines at once

I want to copy rows from one table t2 to another t1, while excluding rows with values already existing in t1. The usual approach of 'NOT IN' works fine but only as long there are not multiple occurences of the same value in the source table t2.
Now, assuming I have two tables with the schema:
CREATE TABLE t1 ( id INTEGER );
CREATE TABLE t2 ( id INTEGER );
then insert data into them like:
INSERT INTO t1 VALUES (1);
INSERT INTO t2 VALUES (1);
INSERT INTO t2 VALUES (2);
Now, I try to insert all data from t2 into t1 but exclude pre-existing in t1:
INSERT INTO t1 (id) SELECT t2.id FROM t2
WHERE t2.id NOT IN ( SELECT t1.id FROM t1 WHERE t1.id = t2.id );
it works flawlessly; the row in t2 with the value of '1' did not get insert a second time into t1:
SELECT * FROM t1;
id
----
1
2
(2 rows)
But when there are multiple occurences of the same value in t2 it doesn't check if they exist in t1 for each individual insert, but for the whole transaction as it seems. Let's continue with my example by:
DELETE FROM t1;
INSERT INTO t2 VALUES (2);
SELECT * FROM t2;
id
----
1
2
2
(3 rows)
INSERT INTO t1 (id) SELECT t2.id FROM t2
WHERE t2.id NOT IN ( SELECT t1.id FROM t1 WHERE t1.id = t2.id );
SELECT * FROM t1;
id
----
1
2
2
(3 rows)
The same result is achieved with WHERE NOT EXISTS as well.
Has anyone an idea of how to check for existing values in t1 on an individual row-level to prevent multiple occurences?
I could as well use ON CONFLICT DO ... but I rather not want to since the idea is to split the data coming from t2 into a "clean" t1 and a "dirty" t1_faulty where all the rows are collected which do not fit some given criteria (one of which the uniqueness of id for which I am asking this question).
I think you could simply filter the records you want from the source table (t2).
you might use distinct on
INSERT INTO t1 (id) SELECT distinct on (t2.id) t2.id FROM t2
WHERE t2.id NOT IN ( SELECT t1.id FROM t1 WHERE t1.id = t2.id );
or group by
INSERT INTO t1 (id) SELECT t2.id FROM t2
WHERE t2.id NOT IN ( SELECT t1.id FROM t1 WHERE t1.id = t2.id ) group by t2.id;
or, if you want only the records that are already unique on t2, add a having count = 1
INSERT INTO t1 (id) SELECT t2.id FROM t2
WHERE t2.id NOT IN ( SELECT t1.id FROM t1 WHERE t1.id = t2.id )
group by t2.id
having count(t2.id) = 1

pl-sql equivalent for t-sql "UPDATE FROM" clause on temp tables

In SQL Server stored procedure I have this code:
UPDATE #tbinforesult
SET prifix = ''
FROM #tbmax t
INNER JOIN #tbinforesult i
ON i.prifix = t.prifix
AND i.PropertyID = t.PropertyID
AND i.GroupID = t.GroupID
AND i.NID <> t.id
What is the equivalent in pl-sql with pl-sql collections not global temporary table?
TSQL :
UPDATE
Table_A
SET
Table_A.col1 = Table_B.col1,
Table_A.col2 = Table_B.col2
FROM
Some_Table Table_A
INNER JOIN
Other_Table Table_B
ON
Table_A.id = Table_B.id
WHERE
Table_A.col3 = 'cool'
PLSQL:
UPDATE table1 t1
SET (name, desc) = (SELECT t2.name, t2.desc
FROM table2 t2
WHERE t1.id = t2.id)
WHERE EXISTS (
SELECT 1
FROM table2 t2
WHERE t1.id = t2.id )
OR:
UPDATE (SELECT t1.id,
t1.name name1,
t1.desc desc1,
t2.name name2,
t2.desc desc2
FROM table1 t1,
table2 t2
WHERE t1.id = t2.id)
SET name1 = name2,
desc1 = desc2
SOURCE :enter link description here

SQL exclude a where clause if the variable is null or empty

I have SQL (postgresql) expression like of these:
select * from table1 t1 left join table2 t2 on t1.id = t2.id where
t1.name = nameVariable and t2.field = fieldVariable;
Would it be possible in case nameVariable is null or empty to not execute the "where
t1.name = nameVariable " at all?
EDIT
Also I need to precise that I am using JPA and hibernate so the query looks like this:
#Query(value = " select * from table1 t1 left join table2 t2 on t1.id = t2.id where
t1.name = :name and t2.field = :fieldName;", nativeQuery=true)
public List<Test> getTest(#Param("name") String name, #Param("fieldName") String fieldName);
SELECT *
FROM table1 t1
LEFT JOIN table2 t2 ON t1.id = t2.id
WHERE (t1.name = nameVariable OR nameVariable IS NULL)
AND (t2.field = fieldVariable OR t2.field IS NULL OR fieldVariable IS NULL)
;

select record from joined table if it exists

I'm working on a sql query that should 'coalesce' the records from 2 tables, i.e. if the record exists in table2, it should take that one, otherwise it should fall back to the values in table1.
In the example, table1 and table2 have just 2 fields (id an description), but obviously in reality there could be more.
Here's a small test case:
create table table1 (id int, description nvarchar(50))
create table table2 (id int, description nvarchar(50))
insert into table1 values (1, 'record 1')
insert into table1 values (2, 'record 2')
insert into table1 values (3, 'record 3')
insert into table2 values (1, 'record 1 modified')
insert into table2 values (2, null)
The result of the query should look like this:
1, "record 1 modified"
2, null
3, "record 3"
Here's what I came up with.
select
case when table2.id is not null then
table2.id else table1.id
end as Id,
case when table2.id is not null then
table2.description
else
table1.description
end as Description
-- etc for other fields
from table1
left join table2 on table1.id = table2.id
Is there a better way to achieve what I want? I don't think I can use coalesce since that would not select a null value from table2 if the corresponding value in table1 is not null.
How about:
SELECT t2.ID, t2.Description
FROM table2 t2
UNION ALL
SELECT t1.ID, t1.Description
FROM table1 t1
WHERE NOT EXISTS (SELECT *
FROM table2 t2
WHERE t2.ID = t1.ID)
The above query gets all the records from table 2 (including the case where description is NULL but the ID is populated), and only the records from table 1 where they don't exist in table 2.
Here's an alternative:
SELECT table2.*
FROM table1
RIGHT JOIN table2
ON table1.id = table2.id
UNION
SELECT table1.*
FROM table1
FULL OUTER join table2
ON table1.id = table2.id
WHERE table1.id NOT IN (SELECT id FROM table2)
--and table2.id not in (select id from table1)
You can add in that last line if you don't want ids that are only in table2. Otherwise I guess Stuart Ainsworth's solution is better (i.e. drop all the joins)
http://sqlfiddle.com/#!3/03bab/12/0