MySQL:如何确定表A和表B中的哪些行在线性时间内被表C中的行引用?
我正在使用一个设计拙劣的数据库,我不能自由地进行重组。在这个数据库中,有三个表,我们称它们为‘companiesA’、‘companiesB’和‘items’,它们涉及我需要优化的查询companiesA'和companiesB'描述公司的方式相同,因为列值相同,但它们代表两个不同的公司组,并且具有不同的列名。本质上,ID和公司名称列在“companiesA”中是“aID”和“aName”,在“companiesB”中是“idB”和“nameB”items'包含一列“companyID”,该列包含来自两个公司表之一的外键值 我需要优化的查询从两个表的并集中获取一个页面的公司ID和名称,按名称列排序,并添加一个列,说明行的公司是否有任何与之关联的项。如果用户在前端请求,此查询还可以按公司名称进行筛选。在它当前的状态下,我认为它在公司*项目时间内运行,速度非常慢:MySQL:如何确定表A和表B中的哪些行在线性时间内被表C中的行引用?,mysql,reference,performance,count,Mysql,Reference,Performance,Count,我正在使用一个设计拙劣的数据库,我不能自由地进行重组。在这个数据库中,有三个表,我们称它们为‘companiesA’、‘companiesB’和‘items’,它们涉及我需要优化的查询companiesA'和companiesB'描述公司的方式相同,因为列值相同,但它们代表两个不同的公司组,并且具有不同的列名。本质上,ID和公司名称列在“companiesA”中是“aID”和“aName”,在“companiesB”中是“idB”和“nameB”items'包含一列“companyID”,该列包
select
a.aID as companyID,
a.aName as companyName,
(select
count(companyID)
from
items
where
companyID = a.aID
) as items
from
companiesA as a
where
a.aName like '%<string>%'
union
select
b.idB as companyID,
b.nameB as companyName,
(select
count(companyID)
from
items
where
companyID = b.idB
) as items
from
companiesB as b
where
b.nameB like '%<string>%'
order by
companyName ASC
limit
[optional_starting_index, ] 50;
items列是否包含实际计数并不重要,因为此查询返回的是一个完整的“items”表的值,这是我唯一能够清楚返回该值的方法。我想我可以算自己幸运,因为有1500家公司和9000个项目,这个算法只需要7秒钟
如果我是用另一种语言写的,我自己也可以用这种语言访问这些表,我可以很容易地用Ocompanies+items来写,但是我发现很难在MySQL中做到这一点。是否可以这样做,最好不使用存储函数或过程?如果需要的话,我可以添加它们,但是我很难通过phpMyAdmin添加它们,因为服务器的主机只允许该接口通过GUI访问数据库。在这个解决方案中,我大胆地假设,通过使用Union All,每个表中的公司名称都是唯一的。如果不是这样,那么你可以切换回Union,但是你会得到让列表独一无二的性能打击。基本上,我消除了使用派生表返回计数的相关子查询的需要
Select Companies.CompanyID, Companies.CompanyName
, Coalesce(ItemTotals.ItemCount,0) As ItemCount
From (
Select a.aID As CompanyID, a.aName As CompanyName
From companiesA As a
Where a.aName Like '%<string>%'
Union All
Select b.IDB, b.nameB
From companiesB As b
Where b.bName Like '%<string>%'
) As Companies
Left Join (
Select companyID, Count(*) As ItemCount
From items
Group By companyID
) As ItemTotals
On ItemTotals.companyID = Companies.CompanyID
Order By Company.CompanyName
在这个解决方案中,我大胆地假设,通过使用UNIONALL,每个表中的公司名称都是唯一的。如果不是这样,那么你可以切换回Union,但是你会得到让列表独一无二的性能打击。基本上,我消除了使用派生表返回计数的相关子查询的需要
Select Companies.CompanyID, Companies.CompanyName
, Coalesce(ItemTotals.ItemCount,0) As ItemCount
From (
Select a.aID As CompanyID, a.aName As CompanyName
From companiesA As a
Where a.aName Like '%<string>%'
Union All
Select b.IDB, b.nameB
From companiesB As b
Where b.bName Like '%<string>%'
) As Companies
Left Join (
Select companyID, Count(*) As ItemCount
From items
Group By companyID
) As ItemTotals
On ItemTotals.companyID = Companies.CompanyID
Order By Company.CompanyName
我测试了这两个版本。第一个在0.2秒以下运行,这很好。第二个需要6.5秒,相当于我的版本,所以它无法运行。不过,谢谢你的回答;这教会了我很多。我测试了两个版本。第一个在0.2秒以下运行,这很好。第二个需要6.5秒,相当于我的版本,所以它无法运行。不过,谢谢你的回答;这教会了我很多。