【问题标题】:Why does a WHERE condition discard content obtained by LEFT JOIN? SQLITE为什么 WHERE 条件会丢弃 LEFT JOIN 获得的内容? SQLITE
【发布时间】:2020-04-07 03:51:54
【问题描述】:

3 个相关表的示例:

  • 用户 2 (Marie) 未在“关系”表中注册。 因此,稍后在使用 SELECT 时,其关系值必须为空/空。

我做了以下 SELECT 来获取我感兴趣的所有相关数据(正确):

SELECT id, action, actions.uid, name, relation
FROM actions
LEFT JOIN (SELECT * FROM relations GROUP BY uid) USING (uid)
INNER JOIN users USING (uid)
GROUP BY actions.id;

然后返回:

当我需要使用条件根据关系类型“丢弃”结果时,就会出现问题。

我进行以下查询以从先前的结果中丢弃“朋友”(关系):

SELECT id, action, actions.uid, name, relation
FROM actions
LEFT JOIN (SELECT * FROM relations GROUP BY uid) USING (uid)
INNER JOIN users USING (uid)
WHERE relation != 'friend'
GROUP BY actions.id;

但是它应该返回一个结果(Marie),它返回 0 个结果...

我对获取 Marie 不感兴趣,因为诸如“...WHERE 关系为 NULL”之类的类型条件,我的查询应该通过丢弃来工作,因为它们属于过滤工具。

【问题讨论】:

  • 这是一个常见问题解答。在考虑发布之前,请阅读手册和谷歌任何错误消息或您的问题/问题/目标的许多清晰、简洁和精确的措辞,有和没有您的特定字符串/名称和站点:stackoverflow.com 和标签;阅读许多答案。请参阅How to Ask 和投票箭头鼠标悬停文本。请use text, not images/links, for text--including tables & ERDs。仅将图像用于无法表达为文本或扩充文本的内容。
  • 如果您不知道:SELECT * FROM relations GROUP BY uid 是无效的标准 SQL,因为您选择的列既不是每组单值也不是聚合的。 SQLite 很高兴地为每个组返回一个随机的relation 值/uid。阅读介绍和您正在使用的手动重新功能。您没有明确说明您想要输入什么输出,因此我们无法知道这是否是错误。你说你的第一个查询没问题,它会随机为 Joe 带上朋友并丢弃邻居,所以我猜你很高兴。
  • 请在代码问题中给出minimal reproducible example--cut & paste & runnable code,包括最小的代表性示例输入为代码;期望和实际输出(包括逐字错误消息);标签和版本;明确的规范和解释。给出您可以给出的最少代码,即您显示的代码可以通过您显示的代码扩展为不正常。 (调试基础。)对于包含 DBMS 和 DDL(包括约束和索引)和输入为格式化为表的代码的 SQL。隔离第一个错误的子表达式及其输入和输出。 (调试基础。)

标签: sql sqlite subquery left-join inner-join


【解决方案1】:

尝试使用 coalesce(Relation,'') != 'friend'。希望它有效

【讨论】:

  • 这是一个极差的答案。请准确说明此代码的去向。请说出为什么它是一个答案。也是错误的。当 PS 代码问题没有 minimal reproducible example 时,应该关闭并投票。如果有一个,那么您可以运行您提出的解决方案,而您不必自己制作一个。重复项也应该关闭,这是一个很容易找到的重复项。 How to AskHow to Answerhelp center
  • 谢谢!这是唯一完全解决我的问题的答案。最终查询将是: SELECT a.id, a.action, a.uid, u.name, coalesce (relation, 'unknown') relantionship FROM actions to INNER JOIN users u USING (uid) LEFT JOIN (SELECT * FROM Relations ) USING (uid) WHERE 关系! =“朋友”和关系! = '邻居' GROUP BY a.id
【解决方案2】:

您需要使用on 子句进行过滤:

SELECT id, action, actions.uid, name, relation
FROM actions LEFT JOIN 
     relations 
     USING (uid) AND relation != 'friend' LEFT JOIN -- Don't mix the left & inner join
     users USING (uid); 

LEFT JOINWHERE 子句将变为 INNER JOIN 并且与 null 比较将始终为 false。因此,在离开时单独过滤。

但是,我将其重新表达为:

SELECT a.id, a.action, a.uid, u.name, r.relation
FROM actions a INNER JOIN
     users u
     USING (uid) LEFT JOIN
     relation r
     USING (uid) AND r.relation != 'friend';

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-20
    • 1970-01-01
    • 1970-01-01
    • 2019-11-13
    • 2019-10-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多