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)
- 网址
- wordid(PK)
- 话
- 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中搜索第一个,因为左连接和其他连接被忽略我想返回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 forplace
和添加总和的想法,它当然给了我一些想法,但是您的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);