快速查明一列的一个值是否与其他 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 语句中完成一项任务时,最好这样做,而不是将数据铲到客户端中让它完成工作。 (通常编码更少!)
我有 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 语句中完成一项任务时,最好这样做,而不是将数据铲到客户端中让它完成工作。 (通常编码更少!)