How to exclude entire Customer ID data based on a condition - sql

I need to exclude all data relating to Customer ID's that have at least one instance where a condition applies. For instance:
This is all my data with conditions
+-------------+----------------+
| Customer ID | Condition |
+-------------+----------------+
| 1 | Contacted |
| 1 | No Answer |
| 1 | Left Voicemail |
| 1 | Spoke to |
| 2 | No Answer |
| 2 | Left Voicemail |
| 3 | Spoke to |
| 3 | No Answer |
| 4 | Contacted |
| 4 | Left Voicemail |
+-------------+----------------+
I need to exclude data with conditions equal to 'Contacted'. Currently, I am using the below code and getting the following results:
SELECT a.customerID,
c.condition
FROM Tablea a
JOIN Tablec c ON
c.customerID = a.customerID
WHERE c.condition NOT LIKE 'Contacted'
+-------------+----------------+
| Customer ID | Condition |
+-------------+----------------+
| 1 | No Answer |
| 1 | Left Voicemail |
| 1 | Spoke to |
| 2 | No Answer |
| 2 | Left Voicemail |
| 3 | Spoke to |
| 3 | No Answer |
| 4 | Left Voicemail |
+-------------+----------------+
However, I would like to exclude all of the Customer ID rows if the Customer ID has the condition. Ideally the code would produce the following:
+-------------+----------------+
| Customer ID | Condition |
+-------------+----------------+
| 2 | No Answer |
| 2 | Left Voicemail |
| 3 | Spoke to |
| 3 | No Answer |
+-------------+----------------+
Any help is greatly appreciated!

This will get you the results you are looking for:
Select customerid, condition from
Tablec c
WHERE customerid NOT IN
(
Select customerid from
Tablec
WHERE condition LIKE 'Contacted'
)
In your above example I am uncertain as to why you are joining to Tablea, as you aren't pulling any data from that table except for customerID, which is already in Tablec.
However if you wanted to do the join, you could do:
Select a.customerID, c.condition from Tablea a
JOIN Tablec c ON c.customerID = a.customerID
WHERE c.customerid NOT IN
(
Select customerid from
Tablec
WHERE condition LIKE 'Contacted'
)

Here's one option using not exists:
select customerid, condition
from Tablec c
where not exists (
select 1
from Tablec c2
where c.customerid = c2.customerid and c2.condition = 'Contacted'
)
This only uses Tablec since it appears to have both customerid and condition. You can always join it back to TableA as needed.

This is slightly hacky but I'm not sure what you're original dataset looks like.
SELECT a.customerID,
c.condition
FROM Tablea a
INNER JOIN Tablec c ON
c.customerID = a.customerID
WHERE c.customerID NOT IN
(
SELECT a2.customerID
FROM Tablec a2
WHERE a2.condition = 'Contacted'
)

Related

How do I receive a pair of ids of entities in many-to-many relation with null value for the second id if condition is not met

I've got the following tables: person (id), person_agency (person_id, agency_id) and agency(id, type)
this is my query:
select p.id, a.id from person p
left join person_agency pa on p.id = pa.person_id
left join agency a on pa.agency_id = a.id
where a.type = 'agency_type1'
However, with the query I get only the persons who have a relation with an agency of "agency_type1". Instead, I would like to get a list of ids of ALL persons with ids of agencies, where the relation exists and null where it doesn't. I tried naive outer joins but it did not work.
For this content of the tables:
Person:
+-------+
| id |
+-------+
| 1 |
| 2 |
| 3 |
| 4 |
+-------+
Person_agency:
+-----------+-----------+
| person_id | agency_id |
+-----------+-----------+
| 1 | 1 |
| 1 | 2 |
| 2 | 4 |
| 4 | 5 |
+-----------+-----------+
Agency:
+--------+------------------+
| id | type |
+--------+------------------+
| 1 | agency_type1 |
| 2 | some_other_type |
| 3 | agency_type1 |
| 4 | agency_type1 |
| 5 | some_other_type |
+--------+------------------+
I receive the folloing output of my query:
+----------+------+
| p.id | a.id |
+----------+------+
| 1 | 1 |
| 2 | 4 |
+----------+------+
The desired output would be:
+----------+------+
| p.id | a.id |
+----------+------+
| 1 | 1 |
| 2 | 4 |
| 3 | null |
| 4 | null |
+----------+------+
It looks like you don't want to distinguish between an agency which is missing and an agency which is present but the wrong type. So you would want a regular JOIN not a LEFT JOIN for the pa/a pair, and also want to filter out the unwanted type directly on that join. Then you want to do a LEFT JOIN from person to the results of that just-described join.
select p.id p_id, a.id a_id from person p
left join (person_agency pa join agency a on pa.agency_id = a.id and a.type='agency_type1')
on p.id = pa.person_id;
p_id | a_id
------+--------
1 | 1
2 | 4
3 | (null)
4 | (null)
The parenthesis around the join pair are not necessary but I find they make it clearer.
If one person is associated to multiple agencies of the correct type, all of them will be shown. I assume this is what you want, although it was not a scenario covered in your example data.
Try to change left join
to
join (inner join).

SQL JOIN two table & show all rows for table A

I have a question about JOIN.
TABLE A | TABLE B |
-----------------------------------------|
PK | div | PK | div | val |
-----------------------------------------|
A | a | 1 | a | 10 |
B | b | 2 | a | 100 |
C | c | 3 | c | 9 |
------------------| 4 | c | 99 |
-----------------------
There are two tables something like above, and I have been trying to join two tables but I want to see all rows from TABLE A.
Something like
SELECT T1.PK, T1.div, T2.val
FROM A T1
LEFT OUTER JOIN B T2
ON T1.div = T2.div
and I want the result would look like this below.
PK | div | val |
-------------------------
A | a | 10 |
A | a | 100 |
B | null | null |
C | c | 9 |
C | c | 99 |
I have tried all JOINs I know but B doesn't appear because it doesn't exist. Is it possible to show all rows on TABLE A and just show null if it doesn't exists on TABLE B?
Thanks in advance!
If you change your query to
SELECT T1.PK, T2.div, T2.val
FROM A T1
LEFT OUTER JOIN B T2
ON T1.div = T2.div
(Note, that div comes from T2 here.), you'll get exactly the result posted (but maybe in a different order, add an ORDER BY clause if you want a specific order).
Your query as it stands will get you:
PK | div | val |
-------------------------
A | a | 10 |
A | a | 100 |
B | b | null |
C | c | 9 |
C | c | 99 |
(Note, that div is b for the row with the PK of B, not null.)
To get to your resultset, all you need to do is use T2.Div as that is the value that does not exist in the second table:
SELECT T1.PK, T2.div, T2.val
FROM A T1
LEFT OUTER JOIN B T2
ON T1.div = T2.div

SQL Server join where not exist on other table

+-------------------+ +-------------------+ +---------------------+
| Service | | Asset | | AssetService |
+-------------------+ +-------------------+ +---------------------+
| Id | Name | | Id | Name | | AssetId | ServiceId |
|-------------------| |-------------------| |---------------------|
| 1 | Service 1 | | 1 | Asset 1 | | 1 | 1 |
| 2 | Service 2 | | 2 | Asset 2 | | 1 | 2 |
| 3 | Service 3 | | 3 | Asset 3 | | 2 | 2 |
+-------------------+ +-------------------+ | 2 | 3 |
+---------------------+
So I have these tables. I want to get the Services that is not on AssetService where AssetId = 1
Like this:
+-------------------+
| Service |
| Id | Name |
+-------------------+
| 3 | Service 3 |
+-------------------+
Is this possible with just inner/left/right join? because I already tried different combinations of inner join but it's not working, like this inner join Asset a on a.Id != as.AssetId. I event tried left and right join.
Can somebody help me?
Thanks.
You can you use an intelligent left join to return non-matching rows only from left table(Service)
SELECT S.Id, S.Name FROM [Service] S
LEFT JOIN ServiceAsset SA
ON S.Id = SA.ServiceId
WHERE SA.ServiceId IS NULL
Note: INNER JOIN returns the matching rows whereas you want the non matching rows then use LEFT JOIN instead
The simplest I can think of:
select * from Service
where Id not in (
select ServiceId
from AssetService
where AssetId = 1);
SQLFiddle link
I don't think it's possible using inner join, because that would only retrieve records that match some criteria and you are looking for records that do not match.
It is, however, possible to do it with left join as Ctznkane525 shows in his answer.
Edit
As jarlh pointed out in the comments, not in might lead to surprising results when there are nulls in the subquery. So, here is the not exists version:
select Id, Name
from Service s
where not exists (
select *
from AssetService a
where AssetId = 1
and ServiceId = s.Id);
SQLFiddle link
Try this:
select * from Service where Id not in (
select ServiceId from AssetService where AssetId = 1
-- we have to filter out NULLs, in case of NULL values query result will be empty
and ServiceId not null
)
It doesn't require any join.
Here is solution with join:
select Id, Name from Service
except
select S.Id, S.Name from Service S join AssetService [AS] on S.Id = [AS].ServiceId
where [AS].AssetId = 1

Access Queries comparing two tables

I have two tables in Access, Table A and Table B:
Table MasterLockInsNew:
+----+-------+----------+
| ID | Value | Date |
+----+-------+----------+
| 1 | 123 | 12/02/13 |
| 2 | 1231 | 11/02/13 |
| 4 | 1265 | 16/02/13 |
+----+-------+----------+
Table InitialPolData:
+----+-------+----------+---+
| ID | Value | Date |Type
+----+-------+----------+---+
| 1 | 123 | 12/02/13 | x |
| 2 | 1231 | 11/02/13 | x |
| 3 | 1238 | 10/02/13 | y |
| 4 | 1265 | 16/02/13 | a |
| 7 | 7649 | 18/02/13 | z |
+----+-------+----------+---+
All I want are the rows from table B for IDs not contained in A. My current code looks like this:
SELECT Distinct InitialPolData.*
FROM InitialPolData
WHERE InitialPolData.ID NOT IN (SELECT Distinct InitialPolData.ID
from InitialPolData INNER JOIN
MasterLockInsNew
ON InitialPolData.ID=MasterLockInsNew.ID);
But whenever I run this in Access it crashes!! The tables are fairly large but I don't think this is the reason.
Can anyone help?
Thanks
or try a left outer join:
SELECT b.*
FROM InitialPolData b left outer join
MasterLockInsNew a on
b.id = a.id
where
a.id is null
Simple subquery will do.
select * from InitialPolData
where id not in (
select id from MasterLockInsNew
);
Try using NOT EXISTS:
SELECT Distinct i.*
FROM InitialPolData AS i
WHERE NOT EXISTS (SELECT 1
FROM MasterLockInsNew AS m
WHERE m.ID = i.ID)

Use COUNT and JOIN in a same query SQL

My tables:
Customers:
+------+----+
| Name | ID |
+------+----+
| Phu | 12 |
| Nam | 23 |
| Mit | 33 |
+------+----+
Orders:
+----+------------+
| ID | Order |
+----+------------+
| 12 | Laptop |
| 12 | Mouse |
| 33 | Smartphone |
| 23 | Keyboard |
| 33 | Computer |
+----+------------+
I want to get output like this:
+------+--------+
| Name | Orders |
+------+--------+
| Phu | 2 |
| Mit | 2 |
+------+--------+
I use this query but this doesn't work:
SELECT
Name,
COUNT(*) AS 'Orders'
FROM
Orders a
INNER JOIN
Customers b ON a.ID = b.ID
GROUP BY
a.ID
HAVING
COUNT(*) > 1;
It has the error like this:
Column 'Customers.Name' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Any help is really appreciated. Thank you.
SELECT c.Name, COUNT(o.ID) AS Orders
FROM Customers c INNER JOIN Orders o ON c.ID = o.ID
GROUP BY o.ID
HAVING Orders > 1
Working Sqlfiddle: http://sqlfiddle.com/#!2/869790/4
As mentioned in my comment every column in the select statement has to be in the group by clause.
SELECT Name, COUNT(*) AS 'Orders'
FROM Orders a
INNER JOIN Customers b
ON a.ID = b.ID
GROUP BY b.Name
HAVING COUNT(*)>1;