2017-06-12 86 views
0

我有如下表SQL与多个表的搜索查询加入

文件

  • 文档ID(PK)
  • 网址

WDATA

  • 的wordID(PK)

wtitle

  • 的wordID
  • 的docID

(的wordID &文档ID组合是唯一的)

wurl

  • 的wordID
  • 文档ID

(wordID的&文档ID组合是唯一的)

搜索我打破它到任何文字短语,并得到其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) 

我有以下怀疑

  1. 如何检查每个表wtitlewurl两个甚至更多作为目前它在因为左wtitle搜索第一个JOIN和其他连接被忽略?
  2. 如何正确构建此SQL查询?

    SQL小提琴http://sqlfiddle.com/#!9/ab0052/4/0

的wordID 3是URL,但不是在DOCID的标题2

的wordID 3是不是在URL,但在DOCID 3的标题

我要回然而,doc 2和3都是因为它首先通过wtitle加入它忽略了(使用第一个查询数据)其他连接

+0

什么可以帮助您创建一些简短的测试数据并为自己进行验证。看看你是否可以得到值来匹配。 –

+1

请注意,'LEFT JOIN w ... WHERE w = ...'与'INNER JOIN w'相同' – Strawberry

+0

如需进一步帮助,请参阅:[为什么我应该为我看来的MCVE一个非常简单的SQL查询?](https://meta.stackoverflow.com/questions/333952/why-should-i-provide-an-mcve-for-what-seems-to-me-to-bea-a-非常简单的sql查询) – Strawberry

回答

1

如果您想知道是否说两个字你重新寻找这两个在一个文件中,你必须看看标题和网址合并。 (否则,如果您知道其中一个词出现在标题中,并且一个词存在于url中,则不知道它是同一个词还是两个词。)因此,首先将两个表与UNION ALL结合起来,但请记住哪个记录属于哪个表。然后我们可以统计每个地点(标题或网址)。

下面是一个查询,查找单词ID 3和4。它列出了只匹配一个关键词匹配两个词在前​​,后跟文件中的条目:

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; 

你可以看一下的话,而不是由

where wordid in (select wordid from wdata where word in ('vaccination', 'the')) 

Rextester链接替换

where wordid in (3,4) 

词ID:http://rextester.com/KPVX67861(SQL拨弄不为我的大部分时间工作。)

我建议这些覆盖索引:

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

随着wordid第一DBMS可以很容易地找到这些条目,并作为docid已经在索引,DBMS不必访问表。它从索引获取所有数据。 (这就是为什么它们被称为覆盖索引的原因;它们涵盖了查询所需的所有列。)

+0

哇非常感谢,我真的很喜欢这个'place'的别名的想法,并添加总和,它当然给了我一些想法,但是你的SQL查询并没有正确使用索引,对于我在'wdata'表和大'wdoc'表中有1000万个数据的情况,执行这个搜索查询需要几分钟的时间。 既然您正在使用'UNION',我将内部条件转移到了更好的性能!更接近我想要的东西!也许我可以用多个积分表来完成联盟,并总结得分或数!谢谢你的帮助 ! –

+1

是的,移动WHERE子句并将其直接应用到表中是个不错的主意。 (我习惯了甲骨文,它的优秀的优化器在内部完成了这个工作,所以我不必两次编写相同的条件。似乎我有点被宠坏了;-)我推荐使用以下两个索引来运行尽可能快:'wtitle(wordid,docid)'和'wurl(wordid,docid)'。在这些索引中首先使用'wordid'是很重要的,所以可以很快找到它们。 DBMS甚至不必读取表格,因为它直接从索引中获得'docid'。 –