【发布时间】:2018-09-30 22:27:53
【问题描述】:
我有 2 个表 Users(Name TEXT) 和 'Coffee Breaks'(Person1 TEXT, Person2 TEXT)。
我需要编写一个联接,它将返回给定用户尚未与咖啡休息时间的所有用户。
我正在尝试在右侧使用 IS NULL 进行左连接。
数据库查询正在完成且没有错误,但我没有在结果中获得任何用户。我的 SQL 查询字符串有问题吗?
SQL:
WITH bilateral(p1, p2) AS (SELECT Person1 AS p1, Person2 AS p2 FROM "Coffee Breaks"
UNION ALL SELECT Person2 AS p1, Person1 AS p2 FROM "Coffee Breaks"
GROUP BY p1, p2)
SELECT * FROM Users u1, Users u2
LEFT JOIN bilateral bi ON u1.Name=bi.p1 AND u2.Name=bi.p2
WHERE bi.p1 IS NULL
样本数据:
Users
[
{
Name: "Casey"
},
{
Name: "Jake"
},
{
Name: "Mark"
},
{
Name: "Steve"
}
]
Coffee Breaks
[
{
Person1: "Steve",
Person2: "Casey"
}
]
服务器代码:
db.neverCoffeed = function(user) {
const sql = `WITH bilateral(p1, p2) AS (SELECT Person1 AS p1, Person2 AS p2 FROM "Coffee Breaks"
UNION ALL SELECT Person2 AS p1, Person1 AS p2 FROM "Coffee Breaks"
GROUP BY p1, p2)
SELECT * FROM Users u1, Users u2
LEFT JOIN bilateral bi ON u1.Name=bi.p1 AND u2.Name=bi.p2
WHERE bi.p1 IS NULL`;
return new Promise((resolve, reject) => {
this.run(sql, (err, users) => {
if (err) {
reject(err);
}
else {
console.log('users', users)
resolve(users);
}
});
});
};
【问题讨论】:
-
SQLite 只是将逗号视为拼写为“交叉连接”。在标准 SQL 逗号中,即“隐式连接”表示交叉连接,但它比使用 JOIN 关键字的“显式连接”绑定得更松散。因此,不要将隐式连接与显式连接混为一谈。 (如果这样做,请将逗号连接放在最后。)在另一个 DBMS 中,您的代码将意味着首先左连接然后交叉连接。由于没有 u1,这会出错。左连接中的列。
-
请阅读minimal reproducible example并采取行动。通过为该功能的最大部分工作的部分代码来证明所需功能的“有问题的最小代码”。表明您的程序在通过(子)表达式时计算出您期望的结果——包括传递给每个函数/运算符的参数是否满足其要求——通过说明这是什么并表明它实际上是通过增量输出完成的。询问示例之间的(小)差异。这是基本调试。 PS您对所需输出作为输出函数的描述不是很清楚。
-
您知道您的 group by 适用于联合的第二个参数,而不是联合吗?对称性表明您不想只对其中一个选择进行分组。无论你打算做什么,都很难知道你想用它做什么。鉴于您最终的左连接左输入,右表中是否存在重复的用户对并不重要,因为您只保留没有匹配的行。但是,如果您确实想要联合后的唯一对,您可以联合 [distinct] 而不是联合所有的 group by。
标签: sql node.js sqlite join left-join