Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/251.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 用于多表联接的搜索查询的SQL_Php_Sql_Join - Fatal编程技术网

Php 用于多表联接的搜索查询的SQL

Php 用于多表联接的搜索查询的SQL,php,sql,join,Php,Sql,Join,我有以下几张表 文档 文档ID(PK) 网址 wdata wordid(PK) 话 wtitle wordid docid (wordid和docid组合唯一) wurl wordid docid (wordid和docid组合唯一) 为了搜索任何短语,我将其分解为单词,并获取其wordid。表wtitle,wurl用于排名行的评分。我打算添加更多用于评分的表,如inlink、inh1标记等。但是,我在构建搜索词的sql查询时遇到了问题 我的SQL查询如下 SELECT d.do

我有以下几张表

文档

  • 文档ID(PK)
  • 网址
wdata

  • wordid(PK)
wtitle

  • wordid
  • docid
(wordid和docid组合唯一)

wurl

  • wordid
  • docid
(wordid和docid组合唯一)

为了搜索任何短语,我将其分解为单词,并获取其
wordid
。表
wtitle
wurl
用于排名行的评分。我打算添加更多用于评分的表,如inlink、inh1标记等。但是,我在构建搜索词的sql查询时遇到了问题

我的SQL查询如下

SELECT d.docid,furl,IF(t.wordid IS NULL,0,1) AS intitle,IF(u.wordid IS NULL,0,1) AS inurl FROM document d
LEFT JOIN wtitle t ON t.docid=d.docid
LEFT JOIN wdata w ON w.wordid=t.wordid
LEFT JOIN wurl u ON u.wordid=w.wordid AND u.docid=d.docid
WHERE w.wordid IN (wordid1,wordid2,wordid3)
我有以下疑问

  • 如何检查每个表
    wtitle
    wurl
    这两个或更多,因为它目前正在wtitle中搜索第一个,因为左连接和其他连接被忽略
  • 如何正确地构建此SQL查询

    SQL小提琴

  • Wordid 3在URL中,但不在文档ID 2的标题中

    Wordid 3不在URL中,但在文档ID 3的标题中


    我想返回doc 2和3,但是因为它首先通过wtitle连接,它忽略了(使用第一个查询数据)其他连接

    如果您想知道,比如说,您要查找的两个单词是否同时出现在文档中,您必须查看title和url的组合。(否则,如果您知道其中一个单词存在于标题中,而另一个单词存在于url中,您将不知道它是同一个单词还是两个单词。)因此,首先将两个表与
    UNION ALL
    组合,但记住哪个记录属于哪个表。然后我们可以计算每个位置(标题或url)的组合和

    下面是一个查找单词IDS3和ID4的查询。它首先列出匹配两个单词的条目,然后列出仅匹配其中一个单词的文档:

    SELECT 
      d.docid, 
      d.furl, 
      w.cnt_combined,
      w.cnt_in_title,
      w.cnt_in_url
    FROM document d
    JOIN
    (
      select
        docid,
        count(distinct wordid) cnt_combined,
        sum(place = 'TITLE') cnt_in_title,
        sum(place = 'URL') cnt_in_url
      from
      (
        select 'TITLE' as place, docid, wordid from wtitle where wordid in (3,4)
        union all
        select 'URL' as place, docid, wordid from wurl where wordid in (3,4)
      ) both_tables
      group by docid
    ) w ON w.docid = d.docid
    order by w.cnt_combined desc;
    
    您可以通过替换来查找单词而不是单词ID

    where wordid in (3,4)
    

    Rextester链接:(SQL fiddle在大多数情况下对我不起作用。)

    我建议采用以下涵盖指数:

    CREATE INDEX idx_wtitle ON wtitle(wordid, docid);
    CREATE INDEX idx_wurl ON wurl(wordid, docid);
    

    使用
    wordid
    首先,DBMS可以轻松地找到条目,而且
    docid
    已经在索引中,DBMS不必访问表。它从索引中获取所有数据。(这就是为什么它们被称为覆盖索引;它们覆盖查询所需的所有列。)

    可以帮助您创建一些简短的测试数据,并亲自验证它。看看你是否能得到匹配的值。注意,
    LEFT JOIN w。。。其中w=…
    内部连接w..相同。
    有关进一步的帮助,请参阅:我已经尝试过了,当我在
    wtitle
    中删除了特定
    docid
    的行,但将其保留在
    wurl
    中,用于
    docid
    停止显示的
    wordid
    相同的
    docid
    !哇,非常感谢,我真的很喜欢alias for
    place
    和添加总和的想法,它当然给了我一些想法,但是您的SQL查询没有正确使用索引,对于我来说,
    wdata
    表和大型
    wdoc
    表中有1000万数据,执行此搜索查询需要几分钟。由于您使用的是
    UNION
    I,因此为了获得更好的性能,我将条件转移到了内部!更接近我想要的东西!也许我可以用许多积分表进行联合运算,并求和得到分数或计数!谢谢你的帮助!是的,将WHERE子句移到内部并将其直接应用于表是一个好主意。(我习惯于Oracle,它的优秀优化器在内部执行此操作,因此我不必编写两次相同的条件。似乎我有点被宠坏了;-)我建议使用以下两个索引以尽快运行此操作:
    wtitle(wordid,docid)
    wurl(wordid,docid)
    。在这些索引中首先使用
    wordid
    非常重要,这样可以快速找到它们。DBMS甚至不再需要读取表,因为它直接从索引中获取
    docid
    CREATE INDEX idx_wtitle ON wtitle(wordid, docid);
    CREATE INDEX idx_wurl ON wurl(wordid, docid);