Return Duplicate emails along with User Ids that are different - sql

I'm running into an issue with a duplicate query and I hope you guys can help.
Essentially what I want to do is find and list of the duplicate emails associated with different userids
My query is:
select UserId, acitveid, email, userstatusid
from (select u.UserId, u.acitveid, cd.email, u.userstatusid,
count(*)over (partition by cd.email) as cnt
from ContactDetails cd
join UserContactDetails ucd on ucd.ContactDetailsId = cd.ContactDetailsId
join dbo.[User] u on u.UserId = ucd.UserId ) ua
where cnt >1
The issue I have with the above query is that it is returning the same userids for some of the results so it looks like:
Userid AcitveId email UserStatusid
123 1 abc#123.com 1
123 1 abc#123.com 1
135 1 efg#123.com 1
142 1 efg#123.com 1
The results Im looking for are simply:
Userid AcitveId email UserStatusid
135 1 efg#123.com 1
142 1 efg#123.com 1

WITH base AS (
SELECT DISTINCT u.UserId
,u.acitveid
,cd.email
,u.userstatusid
,
FROM ContactDetails cd
JOIN UserContactDetails ucd ON ucd.ContactDetailsId = cd.ContactDetailsId
JOIN dbo.[User] u ON u.UserId = ucd.UserId
)
,duplicate_emails AS (
SELECT email
,count(userId) AS cnt
FROM base
GROUP BY 1
HAVING count(userId) > 1
)
SELECT b.*
FROM base b
JOIN duplicate_emails de ON b.email = de.email

A self join across Email = email and id <> id would work fine here. That said, your request and lack of sample data means that we are largely guessing based off the query and sample output you have provided. The below should get you pretty close and, if you update your OP, I am sure we can get you exactly what you're after.
SELECT ActiveUser.UserID Active_UserID,
ActiveUser.ActiveID Active_ActiveID,
ContactDetails.email AS Email,
DuplicateUser.UserID AS Dup_UserID,
DuplicateUser.ActiveID As Dup_ActiveID
FROM ContactDetails INNER JOIN
ContactDetails AS Duplicate ON ContactDetails.email = Duplicate.email AND ContactDetails.UserID <> Duplicate.UserID INNER JOIN
UserContactDetails AS ActiveUserContactDetails ON ActiveUserContactDetails.ContactDetailsID = ContactDetails.ContactDetailsID INNER JOIN
dbo.[User] AS ActiveUser ON ActiveUser.UserID = ActiveUserContactDetails.UserID INNER JOIN
UserContactDetails AS DuplicateUserContactDetails ON DuplicateUserContactDetails.ContactDetailsID = Duplicate.ContactDetailsID INNER JOIN
dbo.[User] AS DuplicateUser ON DuplicateUser.UserID = UserContactDetails.UserID

Related

Subquery SQL for link name and firstname

Hello I would like to retrieve the name and the first name in the user table thanks to the id contained in the message table (id_receive and id_send) in sql via a subquery
SELECT user.nom FROM user
WHERE user.id IN (
SELECT message.id_send, message.id_receive FROM message WHERE message.id=1
)
```
I would recommend using EXISTS, twice:
SELECT u.nom
FROM user u
WHERE EXISTS (SELECT 1 FROM message m WHERE m.id = 1 AND u.id = id_send) OR
EXISTS (SELECT 1 FROM message m WHERE m.id = 1 AND u.id = id_receive) ;
However, a JOIN might also be appropriate:
SELECT u.nom
FROM user u JOIN
message m
ON u.id IN (m.id_send, id_receive)
WHERE m.id = 1;
I suspect it isn't actually what you want but it looks like this is what you're trying to do:
SELECT user.nom FROM user
WHERE user.id IN (
SELECT message.id_send FROM message WHERE message.id=1
UNION ALL
SELECT message.id_receive FROM message WHERE message.id=1
)
The query that drives the IN should return a single column of values
Try and conceive that in works like this:
SELECT * FROM t WHERE c IN(
1
2
3
)
Not like this:
SELECT * FROM t WHERE c IN(
1 2 3
)
Nor like this:
SELECT * FROM t WHERE c IN(
1 2 3
4 5 6
)
It might help you reember that the query inside it must return a single column, but multiple rows, all of qhich are searched for a matching value c by IN
Small addition to your original query to make it working:
SELECT user.nom FROM user
WHERE user.id IN (
SELECT unnest(array[message.id_send, message.id_receive])
FROM message
WHERE message.id=1
)

Error in code. Only one expression can be specified in the select list when the subquery is not introduced with EXISTS

I'm trying to run this query but no matter what I do I keep getting this error and I cannot work it out. Any help would be appreciated.
select
CC.ContactID,
from
Client C
join Contacts CC on CC.ContactID = C.ContactID
where
ClientID In (
Select
ClientID,Sum(Total-allocated) as Bal
from
Main
Where
Total <> Allocated
and NomTypeID < 10
Group By
ClientID
HAVING Sum(Total-allocated) > 10
)
I'm not sure what DB kind you are using (so I also could not test my answer).
But in general when you use IN you need the subquery to return only one column.
So the query should be (removed the Sum(Total-allocated) as Bal):
select
CC.ContactID,
from
Client C
join Contacts CC on CC.ContactID = C.ContactID
where
ClientID In (
Select
ClientID
from
Main
Where
Total <> Allocated
and NomTypeID < 10
Group By
ClientID
HAVING Sum(Total-allocated) > 10
)
Please use below query,
select
CC.ContactID from
Client C
join Contacts CC on CC.ContactID = C.ContactID
join (Select ClientID,Sum(Total-allocated) as Bal from Main Where
Total <> Allocated and NomTypeID < 10
Group By ClientID HAVING Sum(Total-allocated) > 10)) m
on (C.ClientID = m.ClientID);

How to construct SQL query to select chat participants

I have 3 tables. Users(id, fullname), Chats(id, name) and Chats_Participants(chatId, userId). I need to select all the chats in which user with specified id consists. For example:
Chats:
1. 1, 'Test'
Users:
1. 1, 'Test user'
2. 2, 'Test user2'
Chat_Participants:
1. 1(chatId), 1(userId)
2. 1(chatId), 2(userId)
As a result, I need something like this:
1(chatId) 'Test'(chatName) participants(array of users in chat)
First I've wrote this:
select chats.*, json_agg(users) as participants
from chats
inner join chats_participants c2 on chats.id = c2."chatId"
inner join users on c2."userId" = users.id
where users.id = $userId
group by chats.id;
but this query selects only one participant
You can try with array_agg in postgresql. Demo here. Users table is not linked here, printing user id from chat_participants table instead.
SELECT chats.chat_id,chats.name, array_agg(userid order by chats.chat_id)
FROM chats
INNER JOIN chat_participants ON chats.chat_id = chat_participants.chat_id
GROUP BY chats.chat_id,chats.name
You seem to want:
SELECT c.chat_id, c.name,
array_agg(cp.userid order by cp.user_id) as users
FROM chats c INNER JOIN
chat_participants cp
ON c.chat_id = cp.chat_id
GROUP BY c.chat_id, c.name
HAVING SUM( (cp.userid = $userid)::int ) > 0;
This returns only chats that have your user of interest.

select distinct from join

My Tables look like this
Table 1 Table 2
Users Options
id name id user_id option
------- --- -------- --------
1 Donald 1 1 access1
2 John 2 1 access2
3 Bruce 3 1 access3
4 Paul 4 2 access1
5 Ronald 5 2 access3
6 Steve 6 3 access1
Now, i want to select join these to find a user which has only access1
If i do something like
select t1.id,t1.name,t2.id,t2.user_id,t2.option
from table1 t1, table2 t2
where t1.id=t2.user_id
and option='access1';
This does not give me unique results, as in the example i need only user_id=3 my data has has these in hundreds
I also tried something like
select user_id from table2 where option='access1'
and user_id not in (select user_id from table2 where option<>'access1')
There have been other unsuccessful attempts too but i am stuck here
You can do this using a EXISTS subquery (technically, a left semijoin):
SELECT id, name
FROM table1
WHERE EXISTS(
SELECT * FROM table2
WHERE table1.id = table2.user_id
AND table2.option = 'access1'
)
If you want only users that have access1 and not any other access, add NOT EXISTS (a left anti-semi-join; there's a term to impress your colleagues!):
AND NOT EXISTS (
SELECT * FROM table2
WHERE table1.id = table2.user_id
AND table2.option <> 'access1'
)
bool_and makes it simple
with users (id,name) as ( values
(1,'donald'),
(2,'john'),
(3,'bruce'),
(4,'paul'),
(5,'ronald'),
(6,'steve')
), options (id,user_id,option) as ( values
(1,1,'access1'),
(2,1,'access2'),
(3,1,'access3'),
(4,2,'access1'),
(5,2,'access3'),
(6,3,'access1')
)
select u.id, u.name
from
users u
inner join
options o on o.user_id = u.id
group by 1, 2
having bool_and(o.option = 'access1')
;
id | name
----+-------
3 | bruce
If you want the user that has only access1, I would use aggregation:
select user_id
from table2
group by user_id
having min(option) = max(option) and min(option) = 'access1';
WITH users(id,name) AS ( VALUES
(1,'Donald'),
(2,'John'),
(3,'Bruce'),
(4,'Paul'),
(5,'Ronald'),
(6,'Steve')
), options(id,user_id,option) AS ( VALUES
(1,1,'access1'),
(2,1,'access2'),
(3,1,'access3'),
(4,2,'access1'),
(5,2,'access3'),
(6,3,'access1')
), user_access_count AS (
SELECT op.user_id,count(op.option) AS access_count
FROM options op
WHERE EXISTS(
SELECT 1 FROM options
WHERE option = 'access1'
)
GROUP BY op.user_id
)
SELECT u.id,u.name
FROM users u
INNER JOIN user_access_count uac ON uac.user_id = u.id
WHERE uac.access_count = 1;

select count () how to add column

This request gives me the count of the request occurrences where EMAIL occures.
select count(*)
from ADRESS K left outer join ADRESS L
on K.LFDNRSECONDADRESS=L.LFDNR
left outer join ADRESS V
on K.VERLFDNR=V.LFDNR
where ((UPPER(K.EMAIL)= 'my#email.com'
or exists (select ADRESSEMAILADR.LFDNR
from ADRESSEMAILADR
where ADRESSEMAILADR.ADRESSLFDNR=K.LFDNR
and UPPER(ADRESSEMAILADR.EMAIL)=
'my#email.com' )
)) and K.ART='K'
But I also would like go get all occurrences of the column "LFDNR".
Like
3
1234
2345
3456
...
So the first is the count and the followingup are the results of all columns where LFDNR = X.
Of cause I tried
LFDNR, select count(*)
K.LFDNR, select count(*)
And so on...
No luck so far.
If I understand correctly, you want group by:
select k.LFDNR, count(*)
from ADRESS K left outer join
ADRESS L
on K.LFDNRSECONDADRESS = L.LFDNR left outer join
ADRESS V
on K.VERLFDNR = V.LFDNR
where (UPPER(K.EMAIL)= 'my#email.com' or
exists (select ADRESSEMAILADR.LFDNR
from ADRESSEMAILADR
where ADRESSEMAILADR.ADRESSLFDNR = K.LFDNR and
UPPER(ADRESSEMAILADR.EMAIL) = 'my#email.com'
)
) and
K.ART = 'K'
group by k.LFDNR;