SQL check unique key - sql

I hope you're doing fine,
I have a problem to check if my key is unique in my table
Example
ID NAME DATE
1 H 12/12/2022
1 B 11/10/2012
I want to check if the ID can duplicates with other values in Name and Date or not, if all the three are duplicated it's okay, but i want to verify if i can find the same id but with another values.
Thanks
I tried to this :
SELECT ID, NAME , DATE , COUNT(ID)
FROM TABLE t
GROUP BY ID, NAME, DATE
HAVING COUNT(ID) > 1

Try this (For invalid duplicate ID)
SELECT
a.ID, COUNT(1) cnt
FROM TABLE a
INNER JOIN (
SELECT DISTINCT ID, NAME, DATE FROM TABLE
) b ON a.ID = b.ID AND a.NAME != b.NAME AND a.DATE != b.DATE
GROUP BY ID
HAVING COUNT(1) > 1

If your database / table makes any kind of sense it has the feature of primary keys. They MUST be unique and cannot be null. So having a field that is used for IDENTIFYING an entry - thats why it is called ID - please use primary keys in your table and let the DB do it's work.
https://www.w3schools.com/sql/sql_primarykey.ASP

To find id's having invalid duplicate rows, simply do a GROUP BY, and use HAVING to find the invalid rows:
SELECT ID
FROM TABLE
GROUP BY ID
HAVING COUNT(DISTINCT NAME) > 1
OR COUNT(DISTINCT DATE) > 1

Related

How to delete the duplicate data in table (Postgres)

I want to delete the duplicated data in a table , I know there is a way use
SELECT
fruit,
COUNT( fruit )
FROM
basket
GROUP BY
fruit
HAVING
COUNT( fruit )> 1
ORDER BY
fruit;
to find them , buy I need to determine every column's value is equal , which means tableA.* = tableA.* (except id , id is the auto-increment primary key )
and I tried this:
SELECT
*,
COUNT( * )
FROM
myTable
GROUP BY
*
HAVING
COUNT( * )> 1
ORDER BY
id;
but it says I can't use GROUP BY * , so how can I find & delete the duplicated data(need every column's value is equal except id)?
using
SELECT * DISTINCT
DISTINCT remove duplicated result
You need to try something similar to be below query. You apply PARTITION BY for the columns other than Id (as it is incrementing unique value). PARTITION BY should be applied for columns, for which you want to check duplicates.
Also refer to Row_Number in Postgres & Common Table expression in Postgres
WITH DuplicateTableRows AS
(
SELECT Id, Row_Number() OVER (PARTITION BY col1, col2... ORDER BY Id)
FROM
Table1
)
DELETE FROM Table1
WHERE Id IN (SELECT Id FROM Table1 WHERE row_number > 1)
You can do this using JSON:
select (to_jsonb(b) - 'id')
from basket b
group by 1
having count(*) > 1;
The result is as JSON. Unfortunately, to extract the values back into a record, you need to list the columns individually.

DB2 - how to find count multiple occurrences of column value

Im new to DB2 , and tried based on some similar posts, I have a table where I need to find the count of IDs based on where status=P and
the count of(primary=1) more than once.
so my result should be 2 here - (9876,3456)
Tried:
SELECT id, COUNT(isprimary) Counts
FROM table
GROUP BY id
HAVING COUNT(isprimary)=1;
Try the query below:
select ID as IDs,Count(isPrimary) as isPrimary
From Table
where Status = 'p'
Group by ID
Having Count(isPrimary) >1
You are close, I think all you need to do is to add a where clause like:
SELECT id, COUNT(*) as Counted
FROM table
WHERE PrimaryFlag = 1
AND[status] = 'P'
GROUP BY id
EDIT: if you need to count only the distinct IDs, then try:
SELECT COUNT(t.ID) FROM
(
SELECT id, COUNT(*) as Counted
FROM table
WHERE PrimaryFlag = 1
AND[status] = 'P'
GROUP BY id
) as t

Oracle: Select using compound key from subquery

So here's the situation- our records use a compound key of name/date. I want to see all names that have performed 2 specific actions in a row, so I want to do something like
select name from
(select name as n, date as d from table where action='action1'),
(select name from table where name = n and date > d and action='action2' and rownum=1 order by date desc)
but it counts n and d as invalid identifiers. How can I get it to do what I need?
Analytical functions are perfect for this sort of thing.... disclaimer this is quick and dirty and the column names are a little misleading. LAG/LEAD are the options you want to play with
http://sqlfiddle.com/#!4/bd7b2/7
select name,thedate,theaction,prev_action,prev_date from
(
select name,thedate,theaction,
lag(theaction) over (partition by name order by thedate,theaction) as prev_action,
lag(thedate) over (partition by name order by thedate,theaction) as prev_date
from table1
order by name,thedate,theaction
)
where theaction = 'action1' and prev_action = 'action2'
;
One method might be:
SELECT
a1.name
FROM
(SELECT name, date FROM table WHERE action = 'action1') a1
JOIN
(SELECT name, date FROM table WHERE action = 'action2') a2
ON
a2.name = a1.name
AND
a2.date > a1.date
If there can be more than one instance of each action for a single name, this might give you duplicates. In this case, it might be sufficient to use SELECT DISTINCT to eliminate the dups.
Note that this doesn't mean that the two actions happened immediately one after the other, just that action2 happened sometime after action1.

SQL Query to fetch data between starting and ending null

I got a requirement in some project where i need data from a table where i need to select top values that starts after a null value and than again some null values and further data
suppose table name is Data which has a single column named as Company
Company
NULL
NULL
NULL
Google
Microsoft
Oracle
NULL
NULL
Linked In
Twitter
Facebook
NULL
NULL
in simple words i need to write a query that selects {Google, Microsoft and Oracle} as a result and nothing else .... its just a sample data not my actual project
this data can have hundreds of values between starting null and ending null
Please provide your input to write such query
Thanks
Assuming ID is there to keep order... you could do this. This just find the first non-null ID, and then the next null id - 1 as its range.
SELECT *
FROM COMPANY
WHERE ID BETWEEN
( SELECT MIN(ID)
FROM COMPANY
WHERE COMPANY_NAME IS NOT NULL ) AND
( SELECT MIN(ID) - 1
FROM COMPANY
WHERE COMPANY_NAME IS NULL
AND ID > ( SELECT MIN(ID) MIN_ID
FROM COMPANY
WHERE COMPANY_NAME IS NOT NULL ) )
SQL Fiddle Example
Or you could use analytical functions, which would probably be better, assuming you have them in your DBMS.
The easiest way is to use lag():
select d.*
from (select d.*, lag(company) over (order by id) as prev_company
from data d
) d
where prev_company is null and company is not null;
If you don't have lag(), I would use a correlated subquery:
select d.*
from (select d.*,
(select d2.company
from data d2
where d2.id < d.id
order by d2.id desc
limit 1
) as prev_company
from data d
) d
where prev_company is null and company is not null;
Note that in some databases limit might be fetch first row only or select top 1 or some other construct.

How to keep only one row of a table, removing duplicate rows?

I have a table that has a lot of duplicates in the Name column. I'd
like to only keep one row for each.
The following lists the duplicates, but I don't know how to delete the
duplicates and just keep one:
SELECT name FROM members GROUP BY name HAVING COUNT(*) > 1;
Thank you.
See the following question: Deleting duplicate rows from a table.
The adapted accepted answer from there (which is my answer, so no "theft" here...):
You can do it in a simple way assuming you have a unique ID field: you can delete all records that are the same except for the ID, but don't have "the minimum ID" for their name.
Example query:
DELETE FROM members
WHERE ID NOT IN
(
SELECT MIN(ID)
FROM members
GROUP BY name
)
In case you don't have a unique index, my recommendation is to simply add an auto-incremental unique index. Mainly because it's good design, but also because it will allow you to run the query above.
It would probably be easier to select the unique ones into a new table, drop the old table, then rename the temp table to replace it.
#create a table with same schema as members
CREATE TABLE tmp (...);
#insert the unique records
INSERT INTO tmp SELECT * FROM members GROUP BY name;
#swap it in
RENAME TABLE members TO members_old, tmp TO members;
#drop the old one
DROP TABLE members_old;
We have a huge database where deleting duplicates is part of the regular maintenance process. We use DISTINCT to select the unique records then write them into a TEMPORARY TABLE. After TRUNCATE we write back the TEMPORARY data into the TABLE.
That is one way of doing it and works as a STORED PROCEDURE.
If we want to see first which rows you are about to delete. Then delete them.
with MYCTE as (
SELECT DuplicateKey1
,DuplicateKey2 --optional
,count(*) X
FROM MyTable
group by DuplicateKey1, DuplicateKey2
having count(*) > 1
)
SELECT E.*
FROM MyTable E
JOIN MYCTE cte
ON E.DuplicateKey1=cte.DuplicateKey1
AND E.DuplicateKey2=cte.DuplicateKey2
ORDER BY E.DuplicateKey1, E.DuplicateKey2, CreatedAt
Full example at http://developer.azurewebsites.net/2014/09/better-sql-group-by-find-duplicate-data/
You can join table with yourself by matched field and delete unmatching rows
DELETE t1 FROM table_name t1
LEFT JOIN tablename t2 ON t1.match_field = t2.match_field
WHERE t1.id <> t2.id;
delete dup row keep one
table has duplicate rows and may be some rows have no duplicate rows then it keep one rows if have duplicate or single in a table.
table has two column id and name if we have to remove duplicate name from table
and keep one. Its Work Fine at My end You have to Use this query.
DELETE FROM tablename
WHERE id NOT IN(
SELECT id FROM
(
SELECT MIN(id)AS id
FROM tablename
GROUP BY name HAVING
COUNT(*) > 1
)AS a )
AND id NOT IN(
(SELECT ids FROM
(
SELECT MIN(id)AS ids
FROM tablename
GROUP BY name HAVING
COUNT(*) =1
)AS a1
)
)
before delete table is below see the screenshot:
enter image description here
after delete table is below see the screenshot this query delete amit and akhil duplicate rows and keep one record (amit and akhil):
enter image description here
if you want to remove duplicate record from table.
CREATE TABLE tmp SELECT lastname, firstname, sex
FROM user_tbl;
GROUP BY (lastname, firstname);
DROP TABLE user_tbl;
ALTER TABLE tmp RENAME TO user_tbl;
show record
SELECT `page_url`,count(*) FROM wl_meta_tags GROUP BY page_url HAVING count(*) > 1
delete record
DELETE FROM wl_meta_tags
WHERE meta_id NOT IN( SELECT meta_id
FROM ( SELECT MIN(meta_id)AS meta_id FROM wl_meta_tags GROUP BY page_url HAVING COUNT(*) > 1 )AS a )
AND meta_id NOT IN( (SELECT ids FROM (
SELECT MIN(meta_id)AS ids FROM wl_meta_tags GROUP BY page_url HAVING COUNT(*) =1 )AS a1 ) )
Source url
WITH CTE AS
(
SELECT ROW_NUMBER() OVER (PARTITION BY [emp_id] ORDER BY [emp_id]) AS Row, * FROM employee_salary
)
DELETE FROM CTE
WHERE ROW <> 1