Reputation: 47
I want an SQL query that returns a list of users, but only if they have a certain link and not another.
Table 1 links to table 2 users.agreementid = agreements.id, it can link multiple times as a user can be linked to different agreements
All the users in table 1 that only have a link to an agreement where the product is AggregationAgreement, if the user has a link to 2+ agreement ids and any of the links are to a ServiceAgreement then this should not be returned
So I have 2 tables: TABLE 1- USERS
USER AGREEMENTID
--------------------
USER1 1
USER2 3
USER1 3
USER3 3
USER3 4
USER4 1
TABLE 2- AGREEMENTS
ID PRODUCT
-------------------------
1 ServiceAgreement
2 ServiceAgreement
3 AggregationAgreement
4 AggregationAgreement
5 ServiceAgreement
So for my results on the above example i only expect USER2 and USER3 to be returned.
USER 1 has two links but one of those is ServiceAgreement so it shouldn't be returned in the results.
USER 2 has link to just 1 aggregation agreement so this should be returned in the results.
USER 3 has two links but both are to AggregationAgreement so this should be returned in the results.
USER 4 has one link but it's to a ServiceAgreement so this should no be returned in the results.
Hope that all makes sense, as always appreciate any help.
Upvotes: 1
Views: 428
Reputation: 2504
Using EXCEPT:
declare @Users table ([User] nvarchar(10), [AGREEMENTID] int)
insert into @Users values
('USER1', 1)
, ('USER2', 3)
, ('USER1', 3)
, ('USER3', 3)
, ('USER3', 4)
, ('USER4', 1)
declare @Agreements table ([ID] int, [Product] nvarchar(100))
insert into @Agreements values
(1, 'ServiceAgreement')
, (2, 'ServiceAgreement')
, (3, 'AggregationAgreement')
, (4, 'AggregationAgreement')
, (5, 'ServiceAgreement')
select u.[User] from @Users u inner join @Agreements a on u.AGREEMENTID = a.ID and a.Product = 'AggregationAgreement'
except
select u.[User] from @Users u inner join @Agreements a on u.AGREEMENTID = a.ID and a.Product = 'ServiceAgreement'
Upvotes: 1
Reputation: 17126
You can also use a query like below
select user
from
(
select
user=u.[user],
weight= case a.product ='ServiceAgreement' then -1 else 0 end -- negative weight for undesirable agreement
from
users u join agreements a
on u.AgreementId=a.AgreementId
and a.product in ('ServiceAgreement','AggregationAgreement') -- we only have two agreements of interest here
)t
group by [user]
having sum(weight)=0 -- should not be negative
Upvotes: 1
Reputation: 911
This would return the users with the agreements, excluding ones that have a ServiceAgreement linked.
SELECT USERS.[UserName]
, AGREEMENTS.[AgreementId]
, AGREEMENTS.[Product]
FROM USERS
INNER JOIN AGREEMENTS
ON AGREEMENTS.[AgreementId] = USERS.[AgreementId]
WHERE USERS.[UserName] NOT IN
(
SELECT USERS.[UserName]
FROM USERS
INNER JOIN AGREEMENTS
ON AGREEMENTS.[AgreementId] = USERS.[AgreementId]
WHERE AGREEMENTS.[Product] = 'ServiceAgreement'
)
Upvotes: 1
Reputation: 7240
Try this:
select *
from users u
where exists
(
select 1
from agreements a
where u.agreementid=a.id and a.product='AggregationAgreement'
)
and not exists
(
select 1
from agreements a2
where u.agreementid=a2.id and a2.product<>'AggregationAgreement'
)
Upvotes: 1