【问题标题】:Select in select Subquery在选择子查询中选择
【发布时间】:2012-02-28 15:18:10
【问题描述】:

我有 4 张桌子。用户、文章、Langs、LangList

文章表: ..., uid (Users.id), lang (Langs.id),...

LangList 表: id、uid (Users.id)、langid (Langs.id)

我想选择指定用户的所有文章(例如,Users.id = 66),在他选择的语言列表中。

如果我这样做:

function FindActiveLangs($lang){
    $sql ="SELECT langid FROM LangList WHERE `uid`= '66' AND `active`='1';";
    $rsd = mysql_query($sql);
    $lang_string = " ( ".$lang."lang = '0' ";
    while($row = mysql_fetch_array($rsd)){
        $lang_string .= " OR ".$lang."lang = '".$row['langid']."' ";
    }
    $lang_string .= " ) ";
    return $lang_string;
} //end of FindActiveLangs


$tables = " Articles ";
$lang_string = FindActiveLangs("Articles.");
$where1 = "WHERE ".$lang_string." ";
$sql = "select distinct Articles.id, title, descr, thumb, relDate, 
            Articles.alias, Articles.lang, author, source  
        from ".$tables.$where1." and Users";

我在 0.01-0.03 秒内得到结果

第二种方式,我认为更适合简洁的代码:

$sql = "select distinct Articles.id, title, descr, thumb, relDate, 
            Articles.alias, Articles.lang, author, source  
        from Articles 
        where lang IN 
            (SELECT langid FROM LangList WHERE uid= '66' AND active='1')";

我在 1.1-1.3 秒内得到结果

有没有办法执行这个查询,第二种方式性能更好? “IN”会扼杀速度

提前谢谢...

【问题讨论】:

  • Articles 和TagsList 之间没有连接。我不使用 MySql,但在我看来它会产生交叉连接。另外,我没有看到 TagsList 中的任何列被使用。
  • 我忘了删除TagsList,这个查询比这个更高级,我只是为了我遇到的问题重写了它,抱歉现在它已经更新了。

标签: mysql sql select subquery


【解决方案1】:

查看EXISTS 而不是 IN。性能要好很多。

select distinct Articles.id, title, descr, thumb, relDate, Articles.alias, Articles.lang, author, source  
from Articles, TagsList 
where
    Articles.lang = 0 OR 
    EXISTS 
          (SELECT *
           FROM LangList 
           WHERE uid= '66' AND active='1' 
           AND langid = Articles.lang)

编辑:第二次尝试(检查性能是否更好):

SELECT Articles.*
   FROM Articles 
    INNER JOIN LangList
        ON langid = Articles.lang
   WHERE uid= '66' AND active='1' 

UNION

SELECT Articles.*
FROM Articles
WHERE 
Articles.lang=0
AND
NOT EXISTS
(
    SELECT *
           FROM LangList 
           WHERE uid= '66' AND active='1' 
           AND langid = Articles.lang
)

【讨论】:

  • 完美。现在出于优化原因,默认语言是英语,即 id=0。所以我不想将它存储为 LangList 表中每个用户的行。 LangList 表只有额外的语言,例如 Langs.id = 1(法语)、Langs.id=2(德语)。那么我如何修改您的查询以仅接受额外的语言和默认情况下英语 Articles.lang=0?
  • 我找到了:select distinct Articles.id, title, descr, thumb, relDate, Articles.alias, Articles.lang, author, source from Articles, TagsList where EXISTS (SELECT * FROM LangList WHERE uid = '66' AND active='1' AND langid = Articles.lang) or Articles.lang=0 order by relDate DESC
  • @kokazani:我不确定我是否正确理解了表格的工作原理,但您可以尝试使用 OR,就像我修改后的答案一样
  • @kokazani:哎呀...看起来你比我快... :)
  • 不幸的是,现在的响应时间是 1.9 秒 :( 这个概念是我们上传文章,通常是英文,但有时是其他语言。所有用户都可以选择在他们的设置中添加更多语言到查看所有语言的文章,不仅是英文文章。因此,LangList 表仅用于额外的语言存储。如果用户没有选择任何额外的语言,则仅显示英文文章(这使得我们出于优化原因不为英文添加行(langid=0) 在 LangList 表中)
猜你喜欢
  • 1970-01-01
  • 2019-04-04
  • 2021-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-12
  • 2012-02-13
  • 2014-06-08
相关资源
最近更新 更多