快速找出一列的一个值是否存在于同一表中,并具有2或3个其他值
我有3张桌子。一种用于产品,一个用于标签,另一个用于产品标签 - 交配。 这些标签具有不同的级别,并且工作如类别和子类别,但是标签并非直接相互关联。唯一将标签连接到对方(或将子类别放入类别中)的唯一一件事是产品。 想象一下我的ID 1产品,称为Apple iPhone 13 Pro Max 它具有以下标签:
+----+---------------------+-------+
| id | name | level |
+----+---------------------+-------+
| 1 | Telefoon | 1 |
| 2 | Apple | 2 |
| 3 | iPhone 13 Pro Max | 3 |
这意味着products_tags_association表中包含这些行:
+------------+--------+
| product_id | tag_id |
+------------+--------+
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
由于信息组合,我现在知道标签“ telefoon”中有标签“苹果”,并且标签“苹果”有其中的标签“ iPhone 13 Pro Max”。 这就是我在网站上构建菜单的方式。
不过,我现在有一个问题,因为我在products_tags_association表中有一个239 536行的网站。 我正在尝试创建一个逐步选择工具,他们首先从级别选择一个标签,然后选择一个级别的标签,然后选择第3级,但是每个级别的标签只需要是具有所选产品的标签从上一个级别的标签。
我现在拥有的逻辑是:
$sql='SELECT tags.id,level, name FROM tags WHERE tags.level="'.$lvl.'";';
$tags=getDataFromDb($sql,'id');
if(is_array($tags) && is_array($selectedTagsByLvl) && $lvl>1){
foreach($tags as $t=>$tg){
$conditions='';
if(is_array($selectedTagsByLvl)){
foreach($selectedTagsByLvl as $l=>$tgs){
$conditions.=' AND id IN (SELECT product_id FROM products_tags_association WHERE product_id=products.id AND tag_id IN ('.implode(',',$tgs).'))';
}
}
$sql='SELECT id FROM products WHERE online=1 AND id IN (SELECT product_id FROM products_tags_association WHERE product_id=products.id AND tag_id='.$tg['id'].') '.$conditions.' LIMIT 1;';
if(!is_array(getDataFromDb($sql))){
unset($tags[$t]);
}
}
if(count($tags)==0){
return NULL;
}
}
return $tags;
因此,首先,我获得了现在选择的所有标签,然后对于每个标签,我检查是否有一个具有该标签的产品,以及每个标签我在上一步中选择的标签。我应该只能每个级别选择几个标签。 这起作用了,问题在于它太慢了。
我该如何更快地做到这一点?
我需要知道的是,是否有一个product_id与每个选定的tag_id和当前级别的tag_id的组合。也许是product_id的group?
我正在使用PHP和MySQL(Mariadb)
I have 3 tables. One for products, one for tags and one for products-tags-associations.
The tags have different levels and work like categories and subcategories, but the tags are not associated directly to each other. The only thing that connects tags to each other (or put a subcategory in a category) are the products.
Imagine I have the product with the id 1, called Apple iPhone 13 Pro Max
It has the following tags:
+----+---------------------+-------+
| id | name | level |
+----+---------------------+-------+
| 1 | Telefoon | 1 |
| 2 | Apple | 2 |
| 3 | iPhone 13 Pro Max | 3 |
Which means that the products_tags_association table has these rows in it:
+------------+--------+
| product_id | tag_id |
+------------+--------+
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
Because of this combination of information, I now know that the tag "Telefoon" has the tag "Apple" inside it, and the tag "Apple" has the tag "iPhone 13 Pro Max" inside it.
This is how I build the menu on my website.
I now have a problem though, as I have a website with 239 536 rows in the products_tags_association table.
I'm trying to create a step-by step selection tool where they first choose a tag from level 1, then level 2, then level 3, but the tags for each level need to only be the tags that have products which have the selected tag from the previous level.
The logic I have right now is this:
$sql='SELECT tags.id,level, name FROM tags WHERE tags.level="'.$lvl.'";';
$tags=getDataFromDb($sql,'id');
if(is_array($tags) && is_array($selectedTagsByLvl) && $lvl>1){
foreach($tags as $t=>$tg){
$conditions='';
if(is_array($selectedTagsByLvl)){
foreach($selectedTagsByLvl as $l=>$tgs){
$conditions.=' AND id IN (SELECT product_id FROM products_tags_association WHERE product_id=products.id AND tag_id IN ('.implode(',',$tgs).'))';
}
}
$sql='SELECT id FROM products WHERE online=1 AND id IN (SELECT product_id FROM products_tags_association WHERE product_id=products.id AND tag_id='.$tg['id'].') '.$conditions.' LIMIT 1;';
if(!is_array(getDataFromDb($sql))){
unset($tags[$t]);
}
}
if(count($tags)==0){
return NULL;
}
}
return $tags;
So first I get all the tags that have the level I'm selecting right now, and then for each of those tags I check if there is one product that has that tag, plus each of the tags that I've selected in the previous steps. I should only be able to select a few tags per level.
This works, the problem is that it's too slow.
How can I make this faster?
All I need to know is if there is a combination of one product_id with each of the selected tag_id's and the tag_id's for the current level. Maybe something with GROUP BY product_id?
I'm using PHP and mysql (MariaDB)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
然后,
ct
告诉您每个product_id
显示了多少次。在上处理CT> 1
仅列出不止一次发生的产品。一般规则:当您可以在单个SQL语句中执行任务时,这样做比将数据铲到客户端以完成工作要好。 (通常要少进行编码!)
Then,
ct
tells you how many times eachproduct_id
shows up in the table. Tacking onHAVING ct > 1
to list just the products that occur more than once.General rule: When you can do a task in a single SQL statement it is better to do so than shoveling data into the client to have it do the work. (And usually a lot less coding!)