0

I am working on a report that needs to display people who have not done certain training. I have a query that shows people's names and the raining they've done, and another query that shows the entire list of training.

Query #1:

select distinct a.ID, b.Name, b.Descript, b.Code
from Roster a
join SkillCheckOff b on b.Id = a.ID 
order by a.ID, b.Descript

Query #2:

select Descript, Code
from LookupTable 
where Type = 'TRTSkillCheckOff' 
order by Descript

Final result:

Name          Descript
-----------------------
John          Training A
Abbie         Training A
Mike          Training B
...

Basically, if the descript from query #2 is not found from query #1 for each user, the final query needs to display the name and the missing training. Please help.


Based on the answers provided, I think the below query comes close.

with roster as (
select ID
from Roster
), 
skills as (
select Descript, Code from LookupTable where Type = 'TRTSkillCheckOff'
)
select r.ID, s.Descript
from roster r cross join skills s
EXCEPT
select name, Descript
from  SkillCheckOff 

I think using EXCEPT works here.

1
  • Look up NOT EXISTS Commented Jul 15, 2020 at 21:28

3 Answers 3

1

Below the query with CTE and CROSS JOIN:

;WITH CTE_Table AS (
    SELECT DISTINCT 
        A.ID
        ,B.Name
        ,B.Descript
    FROM
        Roster A
        INNER JOIN SkillCheckOff B ON B.ID = A.ID
)
,CTE_Lookup AS (
    SELECT 
        L.Name
        ,L.Descript
    FROM
        Lookup
    WHERE
        Type = 'TRTSkillCheckOff' 
)                 
SELECT 
    C.ID
    ,C.Name
    ,C.Descript
FROM 
    CTE_Table C
    CROSS JOIN CTE_Lookup L 
WHERE 
    L.Descript <> C.Descript
ORDER BY
    C.ID
    ,C.Descript
Sign up to request clarification or add additional context in comments.

7 Comments

Thanks, but this does not return anything.
So all descripts in query1 there are also in query2
I also tested it
I appreciate it, but I tested it as well and did not get anything. For example, I have a user named Mike and he has only done 1 training out of 35. So the query should show me the 34 training names that he did not complete, but it did not.
I understand now. later I will modify the query as required
|
1

You can use NOT EXISTS:

select distinct a.ID, b.Name, b.Descript, b.Code
from Roster a
join SkillCheckOff b on b.Id = a.ID 
WHERE NOT EXISTS (
    select 1
    from LookupTable 
    where Type = 'TRTSkillCheckOff' AND Descript = b.Descript
)

3 Comments

Thanks, but this does not return anything.
@LucasC922 Doesn't return nothing mean everybody has done all training?
No, sir. There are a lot of people who have not.
1

You need to generate all pairs from rosters and skills then match that against the check-off list:

with roster as (
    select ID, Name from Roster
), skills as (
    select Descript, Code from LookupTable where Type = 'TRTSkillCheckOff'
)
select r.Name, s.Descript
from roster r cross join skills s
    left outer join SkillCheckOff k on k.Id = r.Id and k.Code = s.Code
where k.Id is null
order by r.Name, s.Descript;

5 Comments

I think this is close, but the query just shows everyone with the list of every training available, including even the ones that they did.
@LucasC922 The where k.Id is null should eliminate the ones that were actually completed.
@LucasC922 Then I suspect there's something wrong with the join condition. Do the codes match up exactly?
I think rather than using JOIN, using EXCEPT works here. I have modified the query in my original question to show it.
@LucasC922 I looked at your query above. Do the ID and Name columns correspond? That could be the problem with the join. Yes, except in this case.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.