Select non-matching record in same table - SQL - sql

What I am tying to do sounds simple, but cant figure it out. I have a table with a report_number field and a report_type field. The report_number field can have the same "report number" in it as well as the report_type field. I will give some data to better explain what I need to do.
report_number report_type
1 A
2 A
2 B
1 A
3 A
3 A
3 A
4 C
4 C
I need to query for reports that = 'A', but not the SAME report number that also has a report type B associated with it. The results that I would like to get is report #s 1 and 3.
The report number can have different report_types associated with it.
Thanks!

try:
select distinct(report_number)
from reports
where report_type='A' and report_number not in (select report_number from reports where report_type='B')

SELECT DISTINCT a.Report_Number
FROM YourTable a
LEFT JOIN YourTable b
ON a.Report_Number = b.Report_Number
AND a.Report_Type <> b.Report_Number
-- OPTIONAL
AND b.Report_Type = 'B'
WHERE b.Report_Type IS NULL
-- OPTIONAL
AND a.Report_Type = 'A'
EDIT
So far 3 solutions have been posted all adopting a different approach. Check this Link to see which one will suit your RDBMS.

Related

How do I stop my query from pulling duplicates?

Yes, I know this seems simple:
SELECT DISTINCT(...)
Except, it apparently isn't
Here is my actual Query:
SELECT
DeclinationReasons.Reason,
EmployeeInformation.ID,
EmployeeInformation.Employee,
EmployeeInformation.Active,
CompletedTrainings.DecShotDate,
CompletedTrainings.DecShotLocation,
CompletedTrainings.DecReason,
CompletedTrainings.DecExplanation,
IIf([DecShotLocation]="MCS","Yes","No") AS YesMCS,
IIf([DecReason]=1,1,0) AS YesAllergy,
IIf([DecReason]=2,1,0) AS YesImmune,
IIf([DecReason]=3,1,0) AS YesAdverse,
IIf([DecReason]=4,1,0) AS YesMedical,
IIf([DecReason]=5,1,0) AS YesSpiritual,
IIf([DecReason]=6,1,0) AS YesOther,
IIf([DecReason]=7,1,0) AS YesAlready
FROM
EmployeeInformation
INNER JOIN (CompletedTrainings
LEFT JOIN DeclinationReasons ON CompletedTrainings.DecReason = DeclinationReasons.ReasonID)
ON EmployeeInformation.ID = CompletedTrainings.Employee
GROUP BY
DeclinationReasons.Reason,
EmployeeInformation.ID,
EmployeeInformation.Employee,
EmployeeInformation.Active,
CompletedTrainings.DecShotDate,
CompletedTrainings.DecShotLocation,
CompletedTrainings.DecReason,
CompletedTrainings.DecExplanation,
IIf([DecShotLocation]="MCS","Yes","No"),
IIf([DecReason]=1,1,0),
IIf([DecReason]=2,1,0),
IIf([DecReason]=3,1,0),
IIf([DecReason]=4,1,0),
IIf([DecReason]=5,1,0),
IIf([DecReason]=6,1,0),
IIf([DecReason]=7,1,0)
HAVING
((((EmployeeInformation.Active) Like -1)
AND ((CompletedTrainings.DecShotDate + 365 >= DATE())
OR (CompletedTrainings.DecShotDate IS NULL))));
This is Joining a few tables (obviously) in order to get a number of records. The problem is that if someone is duplicated on the table with a NULL in one of the date fields, and a date in another field, it pulls both the NULL and the DATE, or pulls multiple NULLS it might pull multiple dates but those are not present right at the moment.
I need the Nulls, they are actual data in this particular case, but if someone has a date and a NULL I need to pull only the newest record, I thought I could add MAX(RecordID) from the table, but that didn't change the results of the query either.
That code:
SELECT
DeclinationReasons.Reason,
EmployeeInformation.ID,
EmployeeInformation.Employee,
EmployeeInformation.Active,
MAX(CompletedTrainings.RecordID),
CompletedTrainings.DecShotDate
...
And it returned the same issue, Duplicated EmployeeInformation.ID with different DecShotDate values.
Currently it returns:
ID
Active
DecShotDate
etc. x a bunch
1
-1
date date
whatever goes
2
-1
in these
2
-1
date date
columns
These are being used in a report, that is to determine the total number of employees who fit the criteria of the report. The NULLs in DecShotDate are needed as they show people who did not refuse to get a flu vaccine in the current year, while the dates are people who did refuse.
Now I have come up with one simple solution, I could add a column to the CompletedTrainings Table that contains a date or other value, and add that to the HAVING statement. This might be the right solution as this is a yearly training questionnaire that employees have to fill out. But I am asking for advice before doing this.
Am I right in thinking I need to add a column to filter by so that older data isn't being pulled, or should I be able to do this by pulling recordID, and did I just bork that part of the query up?
Edited to add raw table views:
EmployeeInformation Table:
ID
Last
First
empID
Active
Termdate
DoH
Title
PT/FT/PD
PI
1
Doe
Jane
982
-1
date
Sr
PD
X
2
Roe
John
278
0
date
date
Jr
PD
X
3
Moe
Larry
1232
-1
date
Sr
FT
X
4
Zoe
Debbie
1424
-1
date
Sr
PT
X
DeclinationReasons Table:
ReasonID
Reason
1
Allergy
2
Already got it
3
Illness
CompletedTrainings Table:
RecordID
Employee
Training
...
DecShotdate
DecShotLocation
DecShotReason
DecExp
1
1
4
date
location
2
text
2
1
4
3
2
4
4
3
4
date
location
3
text
5
3
4
date
location
1
text
6
4
4
After some serious soul searching, I decided to use another column and filter by that.
In the end my query looks like this:
SELECT *
FROM (
(
SELECT RecordID, DecShotDate, DecShotLocation, DecReason, DecExplanation, Employee,
IIf([DecShotLocation]="MCS","Yes","No") AS YesMCS, IIf([DecReason]=1,1,0) AS YesAllergy,
IIf([DecReason]=2,1,0) AS YesImmune, IIf([DecReason]=3,1,0) AS YesAdverse,
IIf([DecReason]=4,1,0) AS YesMedical, IIf([DecReason]=5,1,0) AS YesSpiritual,
IIf([DecReason]=6,1,0) AS YesOther, IIf([DecReason]=7,1,0) AS YesAlready
FROM CompletedTrainings WHERE (CompletedDate > DATE() - 365 ) AND (Training = 69)) AS T1
LEFT JOIN
(
SELECT ID, Active FROM EmployeeInformation) AS T2 ON T1.Employee = T2.ID)
LEFT JOIN
(
SELECT Reason, ReasonID FROM DeclinationReasons) AS T3 ON T1.DecReason = T3.ReasonID;
This may not have been the best solution, but it did exactly what I needed. Which is to get the information by latest entry into the database.
Previously I had tried to use MAX(), DISTINCT(), etc. but always had a problem of multiple records being retrieved. In this case, I intentionally SELECT the most recent records first, then join them to the results of the next query, and so on. Until I have all the required data for my report.
I write this in hopes someone else finds it useful. Or even better if someone tells me why this is wrong, so as to improve my own skills.

Unable to remove duplicates with subquery

I had a built a query previously that returned zero duplicates until I decided to join in a couple more tables. Now that I've joined them in, I'm unable to create the desired flag due to duplicates being returned. I've attached the scenario below as an example.
I only want one occurrence of each reference number (123456789). I want to create a flag when certain criteria are met. For example, I want to see when reference numbers for a certain account meet "X", but when I join the table I get every instance of that reference number in the joined table.
REFNO BEG END STATUS
123456789 123 456 E
123456789 456 789 E
123456789 789 012 A
I want to see all of the REFNO's based on other parameters set in the query, but I want a flag for anything where END = '012'. I can't left join to the table because I will get all three lines. If I do an inner join then I just get the 012 lines. I Tried the code below in my select statement to only pull when that scenario exists, but I'm getting wacky returns and don't know why. I feel like this should be fairly easy to accomplish, but I can't wrap my head around how to create a flag for just that scenario without getting duplicates or removing results with an inner join.
,(CASE WHEN EXISTS(SELECT 1
FROM QW.ABCD Z
WHERE Z.ABCD = P.ABCD
AND Z.END = '012'
AND Z.TIMESTAMP IS NULL
AND Z.STATUS IN ('A','E'))
THEN 'Y' ELSE 'N'
END)
AS "FLAG"
Please help as I'm not sure what I'm doing wrong to get the flag I want to see.
I am not sure id DB2 allows this combination of UNION and GROUP BY, but what you want is probably something like this:
SELECT 'N' AS FLAG, REF_NO,MIN(BEG),MAX(THEEND) FROM TAB_QW A
WHERE NOT EXIST (SELECT * FROM TAB_QW B WHERE B.REF_NO = A.REF_NO AND B.THEEND = '012')
GROUP BY REF_NO
UNION
SELECT 'Y' AS FLAG, REF_NO,MIN(BEG),MAX(THEEND) FROM TAB_QW C
WHERE EXISTS (SELECT * FROM TAB_QW D WHERE D.REF_NO = C.REF_NO AND D.THEEND = '012')
GROUP BY REF_NO

SQL list multiple Duplicates

running a SQL query in access that is giving me matches where A = record 1, and B also = record 1 , C= record 2 and D E and F also = record 2.
I want my results to display (only max Value)
B =record 1
F= record 2. ( this is a matching query)
basically i want to eliminate duplicates and select "distinct" does not seem to be working for me.
SELECT
FEED_2.ID AS FEED_2_ID,
FEED_3.field_ID,
FEED_3.ID AS FEED_3_ID
FROM FEED_2 INNER JOIN FEED_3 ON FEED_2.[field_ID] = FEED_3.[field_ID]
order by FEED_3.ID
im getting results where feed 2 ID #1,3, and 5 all equal feed 3 - ID #1
i only want feed 2, #5 = feed 3 #1. no Dupes
sorry - hope that helps
It's a shot in the dark but, is something like this you are looking for?
SELECT max(Column_With_ABCDEF), Column_With_record from TABLE_NAME GROUP BY Column_With_record;
If this is not what you are asking for, please do edit your question with your table schema and/or the query you are using so we can help.
---------------- EDIT ----------------
Ok so you can try this:
Select max(FEED_2_ID), field_ID , FEED_3_ID
from (
SELECT FEED_2.ID AS FEED_2_ID, FEED_3.field_ID As field_ID, FEED_3.ID AS FEED_3_ID
FROM FEED_2 INNER JOIN FEED_3
ON FEED_2.[field_ID] = FEED_3.[field_ID]
)
GROUP BY FEED_3_ID, field_ID
ORDER BY FEED_3_ID
The main select is going to group the result from the subquery, that way you should not get duplicated values.
Hope this help

Trying to group items into different categories based on a specific field's value

i cant quite figure out how to put this into a simple question, so I'll explain what I have and what I need to do.
Table A
|..ItemNum..|..ItemUse..|..SubC..|..MainC..|
|..123..|..B..|..AAA..|..QQQ..|
|..456..|..J..|..BBB..|..QQQ..|
|..123..|..D..|..DDD..|..RRR..|
|..789..|..C..|..CCC..|..WWW..|
|..345..|..W..|..EEE..|..TTT..|
|..678..|..B..|..FFF..|..YYY..|
I need to make a list of ItemNum and MainC that are grouped into 3 categories:
B / C / D = 1
<anything else> = 2
B / C / D & <anything else> = 3
So my results would be:
|..MainC..|..Group..|
|..QQQ..|..3..|
|..RRR..|..1..|
|..WWW..|..1..|
|..TTT..|..2..|
|..YYY..|..1..|
I've got an iif setup that takes care of groups 1 and 2, but cant figure out how to get the values in MainC to come out with Group 3.
Any ideas?
I don't understand your explanation ( especially the mapping to 3 ) but here's a shot:
select MainC, case when ItemUse in ('B','C','D') then 1
else 2
end as group
from A

SQL query for aggregate on multiple rows

I have data in a table like following
Name indicator
A 1
A 2
A 3
B 1
B 2
C 3
I want to get count of Names, for which both indicator 1,2 exists. In the preeceding example, this number is 2 (A & B both have indicator as 1, and 2).
The data I am dealing with is moderately large, and i need to get the similar information of some other permutations of (pre defined ) indicators (which i can change, once i get base query).
Try this:
SELECT Name
FROM Tablename
WHERE indicator IN(1, 2)
GROUP BY Name
HAVING COUNT(DISTINCT indicator) = 2;
See it in action here:
SQL Fiddle Demo