快速查明一列的一个值是否与其他 2 个或 3 个值存在于同一 table 中

Fast way to find out if one value of one column exists in the same table with 2 or 3 other values

我有 3 个 table。一种用于产品,一种用于标签,一种用于产品-标签-关联。 标签具有不同的级别,并且像类别和子类别一样工作,但标签之间没有直接关联。唯一将标签相互连接(或将子类别放入类别中)的是产品。 假设我有 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 table 中有这些行:

+------------+--------+
| product_id | tag_id |
+------------+--------+
|          1 |      1 |
|          1 |      2 |
|          1 |      3 |

因为这个信息的组合,我现在知道标签“Telefoon”里面有标签“Apple”,标签“Apple”里面有标签“iPhone 13 Pro Max”它。 这就是我在网站上构建菜单的方式。

我现在遇到了一个问题,因为我的网站在 products_tags_association table 中有 239 536 行。 我正在尝试创建一个循序渐进的 selection 工具,他们首先从第 1 级选择一个标签,然后是第 2 级,然后是第 3 级,但每个级别的标签只需要是具有具有上一级别的 selected 标签的产品。

我现在的逻辑是这样的:

    $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;

所以我首先获取所有具有我现在 select 级别的标签,然后对于每个标签,我检查是否有一个产品具有该标签,加上每个我在前面的步骤中 select 编辑的标签。我应该只能 select 每个级别的几个标签。 这行得通,问题是它太慢了。

我怎样才能让它更快?

我只需要知道是否存在一个 product_id 与每个 selected tag_id 和 tag_id 的组合目前的水平。也许 GROUP BY product_id?

我正在使用 PHP 和 mysql (MariaDB)

SELECT product_id, COUNT(*) AS ct
    FROM table
    GROUP BY product_id

然后,ct 告诉您每个 product_id 在 table 中出现了多少次。继续 HAVING ct > 1 以仅列出出现不止一次的产品。

一般规则:当您可以在单个 SQL 语句中完成一项任务时,最好这样做,而不是将数据铲到客户端中让它完成工作。 (通常编码更少!)