SELECT *
FROM notifications
INNER JOIN COMMENT
ON COMMENT.id = notifications.source_id
WHERE idblog IN (SELECT blogs_id
FROM blogs
WHERE STATUS = "active")
INNER JOIN reportmsg
ON reportmsg.msgid = notifications.source_id
WHERE uid =: uid
ORDER BY notificationid DESC
LIMIT 20;
此处我INNER JOIN
notifications
comment
和reportmsg
;然后使用WHERE
过滤内容。
但我的问题是,对于第一个INNER JOIN
[即,使用comment
],在notifications
加入comment
之前,我希望匹配notifications.idblog
blogs.blogs_id
和 SELECT
仅包含blogs.status = "active"
的行。
为了更好地理解上面的代码:
此处,对于INNER JOIN
,对于comment
,我想SELECT
仅notifications
idblog
匹配blogs.blogs_id
的status = "active"
行并且有INNER JOIN
。
reportmsg
与uid
的第二个PHFetchOptions *options = [[PHFetchOptions alloc] init];
options.includeAssetSourceTypes = PHAssetSourceTypeUserLibrary;
PHFetchResult *allPhotosResult = [PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeImage options:options];
PHImageRequestOptions *requestOptionForPhotos = [[PHImageRequestOptions alloc] init];
requestOptionForPhotos.networkAccessAllowed = YES;
for(PHAsset *asset in allPhotosResult) {
[[PHImageManager defaultManager]
requestImageForAsset:asset
targetSize:CGSizeMake(100, 100)
contentMode:PHImageContentModeAspectFill
options:requestOptionForPhotos
resultHandler:^(UIImage *result, NSDictionary *info) {
NSData *data = UIImagePNGRepresentation(result);
NSString *base = [data base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed]; // for some of photos there is nil
}];
}
无需更改。即,它仅通过src
进行过滤。
答案 0 :(得分:5)
从下图中可以看出,您只需要使用SELECT n.notificationid, n.uid, n.idblog, n.source_id,
b.blogs_id, b.status,
c.id,
r.msgid
-- ... and the other columns you want
FROM notifications n
LEFT JOIN blogs b ON b.blogs_id = n.idblog AND b.STATUS = "active" AND n.uid =: uid
LEFT JOIN comment c ON c.id = n.source_id
LEFT JOIN reportmsg r ON r.msgid = n.source_id
ORDER BY n.notificationid DESC
LIMIT 20;
将其他表合并到通知表中:
infix operator ? : { precedence 120 }
希望这会有所帮助......
答案 1 :(得分:2)
没有必要/理由在第二次连接之前进行过滤,因为你只使用内部连接,然后连接顺序和WHERE条件无关紧要:
SELECT n.*, c.*, r.*
FROM notifications AS n
JOIN COMMENT as c
ON n.source_id = c.id
LEFT JOIN blogs as b
ON n.idblogs = b.blogs_id
AND B.STATUS = 'active'
JOIN reportmsg AS R
ON n.source_id = r.msgid
WHERE uid =: uid
ORDER BY notificationid DESC
LIMIT 20
您可以切换连接顺序,可以将B.STATUS = 'active'
移动到连接条件中,但所有查询都会返回相同的结果。 (编辑后它是LEFT JOIN
,当然现在结果不同了)
当然,您不应该使用*
,最好只列出您实际需要的列。
答案 2 :(得分:1)
如果查询优化器能够正常工作,那么在INNER JOIN
情况下将过滤语句放在哪里并不重要,但在LEFT JOIN
它有效果。在LEFT JOIN
条件中放置过滤语句会导致表首先被过滤,并且在将过滤语句放入WHERE
子句之后加入,将过滤连接的结果。因此,如果您想使用LEFT JOIN
,您的查询必须如下所示:
SELECT nt.*
FROM notifications nt
LEFT JOIN Blogs bg on nt.blogs_id = bg.blogs_id and bg.STATUS = "active"
LEFT JOIN COMMENT cm ON cm.id = nt.source_id
LEFT JOIN reportmsg rm ON rm.msgid = nt.source_id
WHERE uid =: uid
ORDER BY nt.notificationid DESC
LIMIT 20;
答案 3 :(得分:0)
目前还不清楚你的目标是什么......虽然你的表格图很有用,你应该提供一些样本数据和预期结果,即使它只是每个表的几个虚拟行。
查询逐行工作,两个INNER JOIN都应用于同一通知行,并且丢弃不匹配的行。
任何过滤器都适用于两个JOIN,任何返回的行必须在BOTH注释和reportmsg中匹配。
也许您想要两个可以应用不同过滤器的LEFT JOIN并从表名中猜测它可能看起来像这样:
SELECT *
FROM notifications n
LEFT JOIN blogs b
ON n.blogId = b.blogs_id
LEFT JOIN comment c
ON c.id = n.source_id
AND b.status = "Active"
LEFT JOIN reportmsg rm
ON rm.msgid = n.source_id
WHERE n.uid =: uid
AND (c.id IS NOT NULL OR rm.msgid IS NOT NULL)
ORDER BY n.notificationid DESC
LIMIT 20
您还应该遵循命名惯例:
目前,每次要使用时都要查找每个id字段。
答案 4 :(得分:-1)
您应该将查询更改为:
SELECT *
FROM notifications
INNER JOIN comment ON comment.id = notifications.source_id
INNER JOIN reportmsg ON reportmsg.msgid=notifications.source_id
LEFT JOIN blogs ON notifications.idblog = blogs.blogs_id
WHERE blogs.status = 'active'
ORDER BY notificationid DESC
LIMIT 20;