如何在PHP中通过SQL查询获取表数据及解决重复结果问题
解决SQL查询返回重复结果的问题
嘿,我来帮你排查这个重复结果的问题!你的核心问题出在表连接的方式上,咱们一步步拆解:
为什么会出现重复?
你用了SELECT * FROM yt_sub,done WHERE ...这种逗号分隔两个表的写法,这会触发SQL的笛卡尔积连接——简单说就是yt_sub里的每一行,都会和done里所有满足done.link != yt_sub.url AND done.uid != '$id'的行进行匹配。哪怕yt_sub里只有1条符合current < total的记录,只要done里有N条符合条件的行,这条记录就会被返回N次,最终结果自然充满重复。
修正后的查询写法
根据你的需求(从yt_sub选current < total的记录,且这些记录的url没有被uid != $id的用户在done表中标记过),推荐两种更合理的写法:
方法1:用NOT EXISTS子查询(可读性高)
SELECT DISTINCT yt_sub.* FROM yt_sub WHERE yt_sub.current < yt_sub.total AND NOT EXISTS ( SELECT 1 FROM done WHERE done.link = yt_sub.url AND done.uid != '$id' ) ORDER BY RAND() LIMIT 12;
这里的NOT EXISTS会检查:当前yt_sub的url是否没有出现在done表中uid != $id的link字段里,完全符合你的逻辑。加上DISTINCT是双重保险,避免yt_sub自身有重复行的情况。
方法2:用LEFT JOIN + IS NULL(性能友好)
SELECT DISTINCT yt_sub.* FROM yt_sub LEFT JOIN done ON done.link = yt_sub.url AND done.uid != '$id' WHERE yt_sub.current < yt_sub.total AND done.link IS NULL ORDER BY RAND() LIMIT 12;
这种写法是把yt_sub和done做左连接,然后只保留那些在done中没有匹配到的yt_sub行,效果和上面的方法一致,部分数据库对这种写法的优化更好。
额外提醒:避免SQL注入
你直接把$id拼进SQL语句里有安全风险,如果你用的是CodeIgniter框架(从$this->db->query的写法看大概率是),建议用参数绑定的方式:
$query = $this->db->query( "SELECT DISTINCT yt_sub.* FROM yt_sub WHERE yt_sub.current < yt_sub.total AND NOT EXISTS (SELECT 1 FROM done WHERE done.link = yt_sub.url AND done.uid != ?) ORDER BY RAND() LIMIT 12", [$id] );
这样框架会自动处理参数转义,防止SQL注入攻击。
内容的提问来源于stack exchange,提问作者xinaxek
相关产品推荐
相关产品推荐

