使用 NOT IN 子查询返回 0 行的查询
Query with NOT IN subquery returning 0 rows
我遇到了 SQL 查询的问题,理想情况下应该 return 论坛中某个线程的所有评论。
现在我有以下查询:
SELECT p.*, 'BBCode' AS Format,
FROM_UNIXTIME(TIME) AS DateInserted,
FROM_UNIXTIME(editTime) AS DateUpdated
FROM et_post p
LEFT JOIN et_conversation c ON c.conversationId = p.conversationId
WHERE c.private = 0
AND p.postId NOT IN (
SELECT p.postId
FROM et_conversation c
LEFT JOIN et_post p ON p.conversationId = c.conversationId WHERE c.private = 0
GROUP BY p.conversationId
ORDER BY p.TIME
)
然而,这 returns 0 行。我希望它 return 大约 8800 行。
如果我运行单独第一部分:
SELECT p.*, 'BBCode' AS Format,
FROM_UNIXTIME(TIME) AS DateInserted,
FROM_UNIXTIME(editTime) AS DateUpdated
FROM et_post p
LEFT JOIN et_conversation c ON c.conversationId = p.conversationId
WHERE c.private = 0
输出:
# postId, conversationId, memberId, time, editMemberId, editTime, deleteMemberId, deleteTime, title, content, attributes, Format, DateInserted, DateUpdated
'12', '5', '1', '1436600657', NULL, NULL, NULL, NULL, '', 'Content1', ?, 'BBCode', '2015-07-11 09:44:17', NULL
'13', '5', '1', '1436600681', NULL, NULL, NULL, NULL, 'Testing area', 'Content2', ?, 'BBCode', '2015-07-11 09:44:41', NULL
'14', '5', '1', '1436600698', NULL, NULL, NULL, NULL, 'Testing area', 'Content 3', ?, 'BBCode', '2015-07-11 09:44:58', NULL
'15', '5', '19', '1436602065', NULL, NULL, NULL, NULL, 'Testing area', 'More content', ?, 'BBCode', '2015-07-11 10:07:45', NULL
'16', '5', '19', '1436602093', NULL, NULL, NULL, NULL, 'Testing area', 'Even more content', ?, 'BBCode', '2015-07-11 10:08:13', NULL
'17', '5', '1', '1436602137', NULL, NULL, NULL, NULL, 'Testing area', 'Will it ever stop?', ?, 'BBCode', '2015-07-11 10:08:57', NULL
'54', '5', '1', '1436617274', NULL, NULL, NULL, NULL, 'Testing area', 'Ah, final one..', ?, 'BBCode', '2015-07-11 14:21:14', NULL
它 return 有 9304 行像上面这样听起来不错。
运行 单独的子查询:
SELECT p.postId
FROM et_conversation c
LEFT JOIN et_post p ON p.conversationId = c.conversationId WHERE c.private = 0
GROUP BY p.conversationId
ORDER BY p.TIME
输出:
# postId
'12'
'18'
'19'
'44'
'70'
'73'
'75'
它给了我 412 行,就像上面的一样,听起来也不错。
理想情况下,我的最终查询输出应如下所示:
# postId, conversationId, memberId, time, editMemberId, editTime, deleteMemberId, deleteTime, title, content, attributes, Format, DateInserted, DateUpdated
'13', '5', '1', '1436600681', NULL, NULL, NULL, NULL, 'Testing area', 'Content2', ?, 'BBCode', '2015-07-11 09:44:41', NULL
'14', '5', '1', '1436600698', NULL, NULL, NULL, NULL, 'Testing area', 'Content 3', ?, 'BBCode', '2015-07-11 09:44:58', NULL
'15', '5', '19', '1436602065', NULL, NULL, NULL, NULL, 'Testing area', 'More content', ?, 'BBCode', '2015-07-11 10:07:45', NULL
'16', '5', '19', '1436602093', NULL, NULL, NULL, NULL, 'Testing area', 'Even more content', ?, 'BBCode', '2015-07-11 10:08:13', NULL
'17', '5', '1', '1436602137', NULL, NULL, NULL, NULL, 'Testing area', 'Will it ever stop?', ?, 'BBCode', '2015-07-11 10:08:57', NULL
'54', '5', '1', '1436617274', NULL, NULL, NULL, NULL, 'Testing area', 'Ah, final one..', ?, 'BBCode', '2015-07-11 14:21:14', NULL
(注意postId 12不见了)
[编辑]
通过一些快速的头脑计算,我发现以下查询根据行数听起来是正确的 returned:
SELECT p.*, 'BBCode' AS Format,
FROM_UNIXTIME(TIME) AS DateInserted,
FROM_UNIXTIME(editTime) AS DateUpdated
FROM et_post p
INNER JOIN et_conversation c ON c.conversationId = p.conversationId
WHERE c.private = 1
AND p.postId NOT IN (
SELECT DISTINCT po.conversationId
FROM et_post po
);
[编辑2]
现在有了 sqlfiddle
基本上,我希望 id 为 12、15 和 18 的行消失,因为它们是开始对话的人创建的原始帖子。
[编辑3]
现在有了 updated sqlfiddle
- 我对数据库进行了更多挖掘,发现第一个 sqlfiddle 关于数据在数据库中的方式并不是 100% 正确的 - 因此这个更新版本。
省略未使用的 et_conversations
:
SELECT p.*
, 'BBCode' AS Format
, FROM_UNIXTIME(TIME) AS DateInserted
, FROM_UNIXTIME(editTime) AS DateUpdated
FROM et_post p
WHERE EXISTS ( -- suppress the first one
SELECT 1
FROM et_post x
WHERE x.postid = p.postid
AND x.TIME < p.TIME
);
基于已编辑问题中提供的 SQLFiddle,这有效。
SELECT p.*, 'BBCode' AS Format,
FROM_UNIXTIME(TIME) AS DateInserted,
FROM_UNIXTIME(editTime) AS DateUpdated
FROM et_post p
INNER JOIN et_conversation c
ON c.conversationId = p.conversationId
and c.private = 0
join (
select conversationId,min(postId) as m
from et_post
group by conversationId
) r
on r.conversationId = c.conversationId
where p.postId<>r.m
12,15,18 消失 根据您编辑中的要求...NOT IN
疯狂
也是如此
首先,我不知道你想用这个查询实现什么,但我要告诉你你的查询有什么问题..
在第二部分中,您将使用以下查询:
SELECT p.postId
FROM et_conversation c
LEFT JOIN et_post p ON p.conversationId = c.conversationId WHERE c.private = 0
GROUP BY p.conversationId
ORDER BY p.TIME
如果你 运行 它单独给出以下内容:
12,15,18
现在删除 Order by 和 Group by 子句。现在的查询是:。
SELECT p.postId
FROM et_conversation c
LEFT JOIN et_post p ON p.conversationId = c.conversationId WHERE c.private = 0
如果你运行这个查询,你会得到结果:
12,13,14,15,16,17,18,19,20
这些都是 postid 的。
sql 在对它们进行分组之前忽略了所有这些 post id。
因为您的 Group by 子句在逻辑上是错误的。您正在对一列进行分组并选择在这种情况下不是唯一的另一列。
随便。问题是,NOT IN
子句在分组前检查 postid。
您需要更改脚本的逻辑。
这里的问题看起来很简单。让我们分解一下您的陈述:
SELECT p.*, 'BBCode' AS Format,
FROM_UNIXTIME(TIME) AS DateInserted,
FROM_UNIXTIME(editTime) AS DateUpdated
FROM et_post p
LEFT JOIN et_conversation c ON c.conversationId = p.conversationId
WHERE c.private = 0
AND p.postId NOT IN (
SELECT p.postId
FROM et_conversation c
LEFT JOIN et_post p ON p.conversationId = c.conversationId WHERE c.private = 0
GROUP BY p.conversationId
ORDER BY p.TIME
)
在第一部分中,您从 et_post table 和 et_conversation table 中提取所有行,其中 c.private = 0
没有其他条款。
然后在你的 NOT IN
部分,你说:
"Return ALL results where c.private=0
"
然后当然会从外部结果中删除它们。
所以这里发生的事情是:
a) 您正在返回外部语句中的所有记录
b) NOT IN
返回所有基于相同 WHERE
条件的语句
c)每行匹配,当然你得到零结果
听起来您需要将子查询修改为您不想看到的内容。
我遇到了 SQL 查询的问题,理想情况下应该 return 论坛中某个线程的所有评论。
现在我有以下查询:
SELECT p.*, 'BBCode' AS Format,
FROM_UNIXTIME(TIME) AS DateInserted,
FROM_UNIXTIME(editTime) AS DateUpdated
FROM et_post p
LEFT JOIN et_conversation c ON c.conversationId = p.conversationId
WHERE c.private = 0
AND p.postId NOT IN (
SELECT p.postId
FROM et_conversation c
LEFT JOIN et_post p ON p.conversationId = c.conversationId WHERE c.private = 0
GROUP BY p.conversationId
ORDER BY p.TIME
)
然而,这 returns 0 行。我希望它 return 大约 8800 行。
如果我运行单独第一部分:
SELECT p.*, 'BBCode' AS Format,
FROM_UNIXTIME(TIME) AS DateInserted,
FROM_UNIXTIME(editTime) AS DateUpdated
FROM et_post p
LEFT JOIN et_conversation c ON c.conversationId = p.conversationId
WHERE c.private = 0
输出:
# postId, conversationId, memberId, time, editMemberId, editTime, deleteMemberId, deleteTime, title, content, attributes, Format, DateInserted, DateUpdated
'12', '5', '1', '1436600657', NULL, NULL, NULL, NULL, '', 'Content1', ?, 'BBCode', '2015-07-11 09:44:17', NULL
'13', '5', '1', '1436600681', NULL, NULL, NULL, NULL, 'Testing area', 'Content2', ?, 'BBCode', '2015-07-11 09:44:41', NULL
'14', '5', '1', '1436600698', NULL, NULL, NULL, NULL, 'Testing area', 'Content 3', ?, 'BBCode', '2015-07-11 09:44:58', NULL
'15', '5', '19', '1436602065', NULL, NULL, NULL, NULL, 'Testing area', 'More content', ?, 'BBCode', '2015-07-11 10:07:45', NULL
'16', '5', '19', '1436602093', NULL, NULL, NULL, NULL, 'Testing area', 'Even more content', ?, 'BBCode', '2015-07-11 10:08:13', NULL
'17', '5', '1', '1436602137', NULL, NULL, NULL, NULL, 'Testing area', 'Will it ever stop?', ?, 'BBCode', '2015-07-11 10:08:57', NULL
'54', '5', '1', '1436617274', NULL, NULL, NULL, NULL, 'Testing area', 'Ah, final one..', ?, 'BBCode', '2015-07-11 14:21:14', NULL
它 return 有 9304 行像上面这样听起来不错。
运行 单独的子查询:
SELECT p.postId
FROM et_conversation c
LEFT JOIN et_post p ON p.conversationId = c.conversationId WHERE c.private = 0
GROUP BY p.conversationId
ORDER BY p.TIME
输出:
# postId
'12'
'18'
'19'
'44'
'70'
'73'
'75'
它给了我 412 行,就像上面的一样,听起来也不错。
理想情况下,我的最终查询输出应如下所示:
# postId, conversationId, memberId, time, editMemberId, editTime, deleteMemberId, deleteTime, title, content, attributes, Format, DateInserted, DateUpdated
'13', '5', '1', '1436600681', NULL, NULL, NULL, NULL, 'Testing area', 'Content2', ?, 'BBCode', '2015-07-11 09:44:41', NULL
'14', '5', '1', '1436600698', NULL, NULL, NULL, NULL, 'Testing area', 'Content 3', ?, 'BBCode', '2015-07-11 09:44:58', NULL
'15', '5', '19', '1436602065', NULL, NULL, NULL, NULL, 'Testing area', 'More content', ?, 'BBCode', '2015-07-11 10:07:45', NULL
'16', '5', '19', '1436602093', NULL, NULL, NULL, NULL, 'Testing area', 'Even more content', ?, 'BBCode', '2015-07-11 10:08:13', NULL
'17', '5', '1', '1436602137', NULL, NULL, NULL, NULL, 'Testing area', 'Will it ever stop?', ?, 'BBCode', '2015-07-11 10:08:57', NULL
'54', '5', '1', '1436617274', NULL, NULL, NULL, NULL, 'Testing area', 'Ah, final one..', ?, 'BBCode', '2015-07-11 14:21:14', NULL
(注意postId 12不见了)
[编辑] 通过一些快速的头脑计算,我发现以下查询根据行数听起来是正确的 returned:
SELECT p.*, 'BBCode' AS Format,
FROM_UNIXTIME(TIME) AS DateInserted,
FROM_UNIXTIME(editTime) AS DateUpdated
FROM et_post p
INNER JOIN et_conversation c ON c.conversationId = p.conversationId
WHERE c.private = 1
AND p.postId NOT IN (
SELECT DISTINCT po.conversationId
FROM et_post po
);
[编辑2] 现在有了 sqlfiddle
基本上,我希望 id 为 12、15 和 18 的行消失,因为它们是开始对话的人创建的原始帖子。
[编辑3] 现在有了 updated sqlfiddle
- 我对数据库进行了更多挖掘,发现第一个 sqlfiddle 关于数据在数据库中的方式并不是 100% 正确的 - 因此这个更新版本。
省略未使用的 et_conversations
:
SELECT p.*
, 'BBCode' AS Format
, FROM_UNIXTIME(TIME) AS DateInserted
, FROM_UNIXTIME(editTime) AS DateUpdated
FROM et_post p
WHERE EXISTS ( -- suppress the first one
SELECT 1
FROM et_post x
WHERE x.postid = p.postid
AND x.TIME < p.TIME
);
基于已编辑问题中提供的 SQLFiddle,这有效。
SELECT p.*, 'BBCode' AS Format,
FROM_UNIXTIME(TIME) AS DateInserted,
FROM_UNIXTIME(editTime) AS DateUpdated
FROM et_post p
INNER JOIN et_conversation c
ON c.conversationId = p.conversationId
and c.private = 0
join (
select conversationId,min(postId) as m
from et_post
group by conversationId
) r
on r.conversationId = c.conversationId
where p.postId<>r.m
12,15,18 消失 根据您编辑中的要求...NOT IN
疯狂
首先,我不知道你想用这个查询实现什么,但我要告诉你你的查询有什么问题..
在第二部分中,您将使用以下查询:
SELECT p.postId
FROM et_conversation c
LEFT JOIN et_post p ON p.conversationId = c.conversationId WHERE c.private = 0
GROUP BY p.conversationId
ORDER BY p.TIME
如果你 运行 它单独给出以下内容:
12,15,18
现在删除 Order by 和 Group by 子句。现在的查询是:。
SELECT p.postId
FROM et_conversation c
LEFT JOIN et_post p ON p.conversationId = c.conversationId WHERE c.private = 0
如果你运行这个查询,你会得到结果:
12,13,14,15,16,17,18,19,20
这些都是 postid 的。 sql 在对它们进行分组之前忽略了所有这些 post id。 因为您的 Group by 子句在逻辑上是错误的。您正在对一列进行分组并选择在这种情况下不是唯一的另一列。
随便。问题是,NOT IN
子句在分组前检查 postid。
您需要更改脚本的逻辑。
这里的问题看起来很简单。让我们分解一下您的陈述:
SELECT p.*, 'BBCode' AS Format,
FROM_UNIXTIME(TIME) AS DateInserted,
FROM_UNIXTIME(editTime) AS DateUpdated
FROM et_post p
LEFT JOIN et_conversation c ON c.conversationId = p.conversationId
WHERE c.private = 0
AND p.postId NOT IN (
SELECT p.postId
FROM et_conversation c
LEFT JOIN et_post p ON p.conversationId = c.conversationId WHERE c.private = 0
GROUP BY p.conversationId
ORDER BY p.TIME
)
在第一部分中,您从 et_post table 和 et_conversation table 中提取所有行,其中 c.private = 0
没有其他条款。
然后在你的 NOT IN
部分,你说:
"Return ALL results where c.private=0
"
然后当然会从外部结果中删除它们。
所以这里发生的事情是:
a) 您正在返回外部语句中的所有记录
b) NOT IN
返回所有基于相同 WHERE
条件的语句
c)每行匹配,当然你得到零结果
听起来您需要将子查询修改为您不想看到的内容。