What-IF View比较器的UNION NULL的跟进

时间:2018-07-11 16:00:06

标签: sql-server null outer-join cartesian-product

该问题是针对以下问题的后续行动:

purposely union'ing NULLs for a training matrix.

在上一个主题中,我提到了一个具有Job Skills表和Employee Skills表的公司。在此讨论中,我们仅使用其中两名员工...

           jobskills          +             emplskills
job_code skill_desc skill_ID  |  empl_ID emplName job_code skill_ID
-------- ---------- --------  |  ------- -------- -------- --------
   APP      Cut        10     |    396     Tom       APP      10
   APP      Drill      20     |    396     Tom       APP      30
   APP      Bend       30     |    426     Bob       EXP      10
   EXP      Cut        10     |    426     Bob       EXP      20
   EXP      Drill      20     |    426     Bob       EXP      40
   EXP      Bend       30     |    426     Bob       EXP      50
   EXP      Weld       40     |
   EXP      Turn       50     |
                              +

jobskills表中,您将看到APP(学徒)职位需要3种技能-切割,钻孔和弯曲(10、20、30)。同样,EXP(专家)职位需要5种技能(10至50)。

emplskills表中,您将看到Tom是一个学徒(APP),应具有其职务的全部3种技能,但只有2种。他缺少钻孔技能(20)。以同样的方式:专家(EXP)的鲍勃(Bob)应该拥有他的全部5种技能,但缺少弯曲技能(30)。

在上一篇文章中,@ JuanCarlosOropeza创建了此查询(我重新定义了一些列),该查询在每个empl_ID的外部联接NULL,以列出员工具备和不具备的所有技能。

WITH required_skills as 
(
     SELECT DISTINCT 
         e.empl_ID, e.job_code, j.skill_ID, j.skill_desc
     FROM 
         emplskills e
     JOIN 
         jobskills j ON e.job_code = j.job_code
)
SELECT 
    r.empl_ID, e.emplName, r.job_code, r.skill_ID, r.skill_desc
FROM 
    required_skills r
LEFT JOIN 
    emplskills e ON r.empl_ID = e.empl_ID
                 AND r.skill_ID = e.skill_ID;

上面的查询产生了我需要将员工的技能与自己的职称进行比较的结果:

查询结果:

empl_ID emplName job_code skill_ID skill_desc
------- -------- -------- -------- ----------
  396     Tom       APP      10       Cut
  396     Tom       APP      20       Drill
  396    {null}     APP      30       Bend
  426     Bob       EXP      10       Cut
  426     Bob       EXP      20       Drill
  426    {null}     EXP      30       Bend
  426     Bob       EXP      40       Weld
  426     Bob       EXP      50       Turn

此查询的重点是使用该查询作为源视图的Training应用程序。如果用户使用empl_ID进行过滤,则可以查看Tom(396),并发现他缺少Bend技能(30)

过滤汤姆(396)

empl_ID emplName job_code skill_ID skill_desc
------- -------- -------- -------- ----------
  396     Tom       APP      10       Cut
  396     Tom       APP      20       Drill
  396    {null}     APP      30       Bend

...现在是新问题:

在培训应用程序中,我需要将员工与任何职位进行比较。因此,我需要使用job_codes的每种可能组合以及技能的每种可能组合来使每个员工外在参与。

我真正需要的查询的期望结果是这样的:

empl_ID emplName job_code skill_ID skill_desc
------- -------- -------- -------- ----------
  396     Tom       APP      10       Cut
  396     Tom       APP      20       Drill
  396    {null}     APP      30       Bend
  396     Tom       EXP      10       Cut
  396     Tom       EXP      20       Drill
  396    {null}     EXP      30       Bend
  396    {null}     EXP      40       Weld
  396    {null}     EXP      50       Turn
  426     Bob       APP      10       Cut
  426     Bob       APP      20       Drill
  426     Bob       APP      30       Bend
  426     Bob       EXP      10       Cut
  426     Bob       EXP      20       Drill
  426    {null}     EXP      30       Bend
  426     Bob       EXP      40       Weld
  426     Bob       EXP      50       Turn

现在,当用户进行过滤时,他们可以将员工与不同职务中的需求进行比较。对于学徒汤姆,对学徒头衔的原始过滤仍然有效:

Filter on Tom(396) and JOB CODE (APP)
empl_ID emplName job_code skill_ID skill_desc
------- -------- -------- -------- ----------
  396     Tom       APP      10       Cut
  396     Tom       APP      20       Drill
  396    {null}     APP      30       Bend

但是,如果考虑将Tom提升为EXPERT,则经理可以立即查看Tom缺少哪些专家技能:

Filter on Tom(396) and JOB CODE (EXP)
empl_ID emplName job_code skill_ID skill_desc
------- -------- -------- -------- ----------
  396     Tom       EXP      10       Cut
  396     Tom       EXP      20       Drill
  396    {null}     EXP      30       Bend
  396    {null}     EXP      40       Weld
  396    {null}     EXP      50       Turn

有没有一种方法可以更改上述查询来完成此操作?到目前为止,我对您提供的帮助非常感谢。这是我目前工作中的现实挑战。我们拥有约150名实际的工厂工人,涵盖40多个职位。其中一些职位具有超过3打的Skill_ID。

最后,我尝试使用上述查询创建VIEW AS(),但语法不正确。新查询正常工作后,您能帮我将其转换为CREATE VIEW语句吗?

再次感谢, 约翰

1 个答案:

答案 0 :(得分:1)

您实际上应该以消耗性格式发布数据。幸运的是,Juan Carlos Opreza在上一个问题中为您做到了。我带走了他,并从另一个问题中删除了“额外”数据。

CREATE TABLE emplskills 
    ([empl_ID] int, [emplName] varchar(3), [job_code] varchar(3), [skill_ID] int)
;

INSERT INTO emplskills 
    ([empl_ID], [emplName], [job_code], [skill_ID])
VALUES
    (396, 'Tom', 'APP', 10),
    (396, 'Tom', 'APP', 20),
    (426, 'Bob', 'EXP', 10),
    (426, 'Bob', 'EXP', 20),
    (426, 'Bob', 'EXP', 40),
    (426, 'Bob', 'EXP', 50)
;


CREATE TABLE jobskills 
    ([job_code] varchar(3), [skill_desc] varchar(5), [skill_ID] int)
;

INSERT INTO jobskills 
    ([job_code], [skill_desc], [skill_ID])
VALUES
    ('APP', 'Cut', 10),
    ('APP', 'Drill', 20),
    ('APP', 'Bend', 30),
    ('EXP', 'Cut', 10),
    ('EXP', 'Drill', 20),
    ('EXP', 'Bend', 30),
    ('EXP', 'Weld', 40),
    ('EXP', 'Turn', 50)
;

现在,我们需要处理一些具体且确定的事情,让我们看看这可能如何工作。由于左连接不起作用,因为在没有匹配项的情况下将填充empl_ID,因此需要一些不同的方法。解决这一问题的方法不止一种。我使用交叉联接生成了所有雇员和工作技能的列表。这给了我们您可以在左联接中使用的列表。

我不得不说,由于这些结构非常痛苦,因此您需要阅读规范化知识。

select AllEmpSkills.empl_ID
    , es.emplName
    , js.job_code
    , js.skill_ID
    , js.skill_desc
from jobskills js
cross join 
(
    select distinct empl_ID from emplskills
) AllEmpSkills
left join emplskills es on es.empl_ID = AllEmpSkills.empl_ID
                    and es.skill_ID = js.skill_ID
order by AllEmpSkills.empl_ID
    , js.job_code
    , js.skill_ID