fetching duplicate tuples in Oracle using SQL - sql

Here are the two table structures
I have two tables where I am trying to fetch some duplicate records based on some condition like where a.fname=b.fname and a.phone_no<>b.phone_no
But also I need to include other column 'address' which is in table 2 and introduce the same condition for duplicate checking for address as well.
SELECT
"Fname"||' '||"Lname" AS "Customer_Name",
COUNT(*) AS "Countof"
FROM "S_CONTACT" A
WHERE EXISTS (
SELECT 1
FROM "S_CONTACT" B
WHERE A."PHONE" != B."PHONE"
AND A."Fname" = B."Fname"
AND A."EMAIL"=B."EMAIL"
AND A."Lname"=B."Lname"
AND "DOB" IS NULL
)
GROUP BY "Fname","Lname","EMAIL"
HAVING count(*) >1;
The above sql gives me a list of customers with duplicate names and email.
But I do not know how to introduce the column address in this sql which is from different table t2

If you are trying to find duplicates in one table:
select c.fname, c.lname, c.email
from contacts c
group by c.fname, c.lname, c.email
having min(c.phone) <> max(c.phone);
If you want to count null as a different value, then use:
having min(c.phone) <> max(c.phone) or count(c.phone) <> count(*)
You can do the same thing on the second table:
select c.fname, c.lname, c.email
from second_table c
group by c.fname, c.lname, c.email
having min(c.address) <> max(c.address) or count(c.address) <> count(*)
If you need the results in the same result set, then use union or union all or some similar mechanism.

Related

How to use INTERSECT together with COUNT in SQLite?

I have a table called customer_transactions and a table called blacklist.
The customer_transactions table has a column called atm_name.
Both tables share a unique key called id.
How can I intersect the two tables in such a way that the query shows me
customers that appear on both tables.
a corresponding column that displays the times that they had used a
certain atm alongside the atm's name
(for instance: id_1 -- bank of america -- 2; id_1 -- citibank -- 3;
id_2 -- bank of america -- 1; id_2 -- citibank -- 4, etcetera).
I have something like this
SELECT id,
atm_name,
count(atm_name) as atm_count
FROM customer_transactions
GROUP BY id, atm_name
How can I INTERSECT this table with the blacklist table and maintain what I currently have as output?
Thanks in advance.
You seem to want a join. Assuming that column id relates the two tables, and that it is a unique key in blacklist, you can do:
select ct.id, ct.atm_name, count(*) as atm_count
from customer_transactions ct
inner join blacklist b on b.id = ct.id
group by ct.id, ct.atm_name
You can also express this logic with exists and a correlated subquery:
select ct.id, ct.atm_name, count(*) as atm_count
from customer_transactions ct
where exists (select 1 from blacklist b where b.id = ct.id)
group by ct.id, ct.atm_name

Looking to find duplicate emails but with having a different name in one table

Hello I am trying to find what customer have the same emails but having a different name. Pretty much what happen is in our name, first name, last name it populate the email name so it looks like janedoe-at-yahoo. So was able to find all the -at- now I want to match those emails with the correct name Jane Doe so I can fix all the -at- emails. Hope that all made sense please help.
SELECT C.CUST_NO, C.NAM, C.EMAIL_ADRS_1
FROM AR_CUST C
INNER JOIN (SELECT NAM, EMAIL_ADRS_1, COUNT(*) AS COUNTOF
FROM AR_CUST
GROUP BY NAM, EMAIL_ADRS_1
HAVING COUNT(*)>1
) DT ON C.NAM = DT.NAM AND C.EMAIL_ADRS_1 = DT.EMAIL_ADRS_1
ORDER BY C.EMAIL_ADRS_1
This code will bring up all the duplicate emails only
SELECT C.CUST_NO, C.NAM, C.FST_NAM, C.LST_NAM, C.EMAIL_ADRS_1
FROM AR_CUST C
INNER JOIN (SELECT NAM, EMAIL_ADRS_1, COUNT(*) AS COUNTOF
FROM AR_CUST
GROUP BY NAM, EMAIL_ADRS_1
HAVING COUNT(*)>1 AND NAM LIKE '%-at-%'
) DT ON C.EMAIL_ADRS_1 = DT.EMAIL_ADRS_1
ORDER BY C.EMAIL_ADRS_1
This code will bring me the -at- emails and some of the correlate names but it only brings me 100 records when there should be at least 900 records
Hello I am trying to find what customer have the same emails but having a different name.
If you just wand the email address that are duplicates, you can answer this with aggregation:
SELECT C.EMAIL_ADRS_1
FROM AR_CUST C
GROUP BY C.EMAIL_ADRS_1
HAVING MIN(C.NAM) <> MAX(C.NAM);
If you want the original records, use exists:
select c.*
from ar_cust c
where exists (select 1
from ar_cust c2
where c2.email_adrs_1 = c.email_adrs_1 and
c2.nam <> c.nam
);

SQL Query – records within the SQL Select statement, but NOT in the table being queried

I have a large list of CustIDs that I need to query on to find if they are within the CUSTOMER table; I want the result to tell me which CustIDs ARE on the table and which CustIDs are NOT on the table.
I provided a short list below to give an idea of what I need to do.
Oracle database
Table: Customer
Primary Key: CustID
Scenario:
Customer table only has the following (2) CustID: ‘12345’, ‘56789’
Sql:
Select * from CUSTOMERS where CUSTID in (‘12345’, ‘56789’, ‘01234’);
I want the result to tell me that both ‘12345’ and ‘56789’ are in the table, AND that ‘01234’ is NOT.
select
v.CustID,
exists (select * from Customer where Customer.CustID = v.CustID)
from (values (12345), (56789), (01234)) v (CustID);
Results:
custid exists
12345 true
56789 true
1234 false
You need a left join or subquery for this. The precise syntax varies by database. Typical syntax is:
select i.custid,
(case when c.custid is not null then 1 else 0 end) as exists_flag
from (select '12345' as custid union all
select '56789' union all
select '01234'
) ci left join
customers c
on c.cust = i.custid;

Alias table that's actually a pivoted one?

I have this query:
SELECT
A.USERID
A.NAME
PVT.PHONE 'PROBABLY A CASE STATEMENT ON NULL WILL GO HERE...
PVT.ADDRESS 'ON HERE AS WELL...
FROM
USERS A
'I NEED TO CREATE A PIVOT TABLE HERE WITH THE ALIAS OF 'PVT' ON TABLE 'B'
B Contents:
UserID PHONE ADDRESS TYPE
1 444-555-2222 XXXXXXX PHONE
1 XXXXXXX 66 Nowhere NOTADDRESS
I want, on the same row, the user's phone by getting B.PHONE if TYPE = 'PHONE'.
I also want, on the same row, the user's address by getting B.ADDRESS content if TYPE = 'ADDRESS'.
As you see in the table dump above, I don't have a record matching the user ID AND TYPE = 'ADDRESS'
So I would need to show a blank or 'No address' in the main SELECT which will show the phone, but on the same row, blank or 'No address'.
I don't want to create an INNER JOIN because if there are no matching UserID's in B, the query will not return the info that I have in table A for that user.
Also, a LEFT JOIN will create two rows, which I don't want.
I think I pivoted table as alias would do it, but I don't know how to create such an alias.
Any ideas ?
How about using conditional aggregation?
SELECT A.USERID, A.NAME
B.PHONE, B.ADDRESS
FROM USERS A LEFT JOIN
(SELECT UserId, MAX(CASE WHEN TYPE = 'PHONE' THEN PHONE END) as PHONE,
MAX(CASE WHEN TYPE = 'ADDRESS' THEN ADDRESS END) as ADDRESS
FROM B
GROUP BY UserId
) B
ON B.UserId = A.UserId;
If you have to use PIVOT then you'd need the pivot in a subquery and left join to it
SELECT
A.USERID,
A.NAME,
PVT.PHONE,
PVT.[ADDRESS]
FROM
Users A
LEFT JOIN (SELECT *
FROM
(SELECT
UserID,
[Type],
(CASE [Type] WHEN 'PHONE' THEN PHONE WHEN 'ADDRESS' THEN [Address] END) Info
FROM UserInfo) AS UI
PIVOT (
MAX(Info)
FOR [Type] IN ([PHONE], [ADDRESS])
) P
) PVT ON A.UserID = PVT.UserID
This gives you pretty much the same execution plan as the conditional aggregation query, but not as easy on the eyes.
SQL Fiddle

SQL Database with duplicate

Say I have multiset in my table and with the below I will get the duplicates
select name, address from users group by
name, address having count(*) > 1
But my problem is ... say I have another field called credit. I would want to compare credits in the duplicate values and would take the second if the second credit is higher than the first (that is max)
select name, address, from users group by
name, address having count(*) > 1
use
select A.name, A.address, max ( A.credits ) mc from users A
where (A.name, A.address) in
(
select B.name, B.address from users B group by
B.name, B.address having count(*) > 1
)
group by A.name, A.address