具有多列且可能返回null的子查询SQL

问题描述

我有一些表需要从中提取信息,但是我觉得可以优化这种方式。 上下文是一个玩家向另一个玩家提供信息。这些信息是游戏的知识元素,因此已经在表“ knlist”中定义。谁提供的信息存储在“ knlogs”表中。

因此,当一个玩家想要将信息提供给另一位玩家时,它首先需要查看该玩家是否已经拥有该信息。因此,我想要的是该球员的全部知识的清单,另外的列表示是否已有其他球员拥有的日志。 用子查询就足够简单了,但是在我需要这个可能的日志中的另一个信息之后,所以子查询中的第二列。在这里,我无法加入表,因为完全有可能日志根本不存在。我需要在列中返回空值。

这是我现在做这个的方式。问题是我有两个子查询可以访问完全相同的行(如果存在)。

表格: 请注意,每列中都有更多列,但为简单起见...

knlist                                | knlogs
                                      |
idkNowledge        description        | idkNowledge        idlearner          datekNowledge      datetheory
----------------   ----------------   | ----------------   ----------------   ----------------   ----------------
1                  Some text.         | 1                  6166               2020-08-07         0000-00-00
2                  Some more text.    | 2                  6166               2020-08-07         0000-00-00
3                  Sample data.       | 1                  3069               2020-08-01         0000-00-00
4                  Even more text.    | 3                  3069               0000-00-00         2019-12-31

让我们假设用户6166要向用户3069提供一些信息。我想看看3069是否已经拥有该信息或它的理论。

SELECT li.description,li.idkNowledge,(SELECT datetheory FROM knlogs where idkNowledge=li.idkNowledge and idlearner=3092) as datetheory_user_2,(SELECT datekNowledge FROM knlogs where idkNowledge=li.idkNowledge and idlearner=3092) AS datekNowledge_user_2
FROM knlist as li,knlogs as lo
WHERE li.idkNowledge=lo.idkNowledge and lo.idlearner=6166

这就是我所拥有的,并且有效。它返回:

description        idkNowledge        datetheory_user_2         datekNowledge_user_2
----------------   ----------------   -----------------------   -----------------------
Some text.         1                  0000-00-00                2020-08-01                
Some more text.    2                  NULL                      NULL

现在,请求仅在两个不同的列上包含相同的子查询。我认为由于可能为NULL,所以我无法与FROM部分中选择的另一个表联接。如果要这样做,我将跳过返回的第二行。

有人能替代这个吗?谢谢。

解决方法

从不FROM子句中使用逗号。 始终使用正确的,明确的,标准,可读的JOIN语法。

如果要避免子查询,只需使用left join

SELECT li.description,li.idknowledge,lo2.datetheory as datetheory_user_2,lo2.dateknowledge as dateknowledge_user_2
FROM knlist li join
     knlogs lo
     on li.idknowledge = lo.idknowledge left join
     knlogs lo2
     on lo2.idknowledge = lo.idknowledge and
        lo2.idlearner = 3092
WHERE lo.idlearner = 6166;