php - 在 MySQL 中实现 SQL INTERSECT 时嵌套级别太高

标签 php mysql yii

我最近的作品之一是基于 Yii 的硬件目录。每个项目都可以链接到很多组。

CREATE TABLE item_group (
id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
itemId INT(10) UNSIGNED NOT NULL,
groupId INT(10) UNSIGNED NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

只有那些 itemIds 必须显示,其中包含用户选择的所有 groupIds。这是我的错误解决方案:

$groups = isset($_GET['groups']) ? array_merge(array_diff($_GET['groups'], array('0'=>'-')),array()) : array();
$sql = '';
$brackets = '';
$groupMaxKey = count($groups) - 1;
//some code here
for($i=0;$i<=$groupMaxKey;$i++){
    $sql .= "SELECT itemId FROM item_group WHERE groupId='".$groups[$i]."' ";
    if($i != $groupMaxKey){
        $sql .= "AND itemId IN (";
        $brackets .= ")";
    } else {
        $sql .= $brackets;
    }
}

我发现最大嵌套层数是32层,层数多了报错。最干净的解决方案是什么?

在这里澄清一个查询示例:

SELECT itemId FROM item_group 
WHERE groupId='31' AND itemId IN (
    SELECT itemId FROM item_group 
    WHERE groupId='24' AND itemId IN (
        SELECT itemId FROM item_group 
        WHERE groupId='35'
    )
)

//// 答案确实有效:

SELECT g1.itemId 
FROM ((((((((((((((((((((((((((((((((((((((( item_group g1 
INNER JOIN item_group g2 ON g1.itemId = g2.itemId)
INNER JOIN item_group g3 ON g1.itemId = g3.itemId)
INNER JOIN item_group g4 ON g1.itemId = g4.itemId)
INNER JOIN item_group g5 ON g1.itemId = g5.itemId)
INNER JOIN item_group g6 ON g1.itemId = g6.itemId)
INNER JOIN item_group g7 ON g1.itemId = g7.itemId)
INNER JOIN item_group g8 ON g1.itemId = g8.itemId)
INNER JOIN item_group g9 ON g1.itemId = g9.itemId)
INNER JOIN item_group g10 ON g1.itemId = g10.itemId)
INNER JOIN item_group g11 ON g1.itemId = g11.itemId)
INNER JOIN item_group g12 ON g1.itemId = g12.itemId)
INNER JOIN item_group g13 ON g1.itemId = g13.itemId)
INNER JOIN item_group g14 ON g1.itemId = g14.itemId)
INNER JOIN item_group g15 ON g1.itemId = g15.itemId)
INNER JOIN item_group g16 ON g1.itemId = g16.itemId)
INNER JOIN item_group g17 ON g1.itemId = g17.itemId)
INNER JOIN item_group g18 ON g1.itemId = g18.itemId)
INNER JOIN item_group g19 ON g1.itemId = g19.itemId)
INNER JOIN item_group g20 ON g1.itemId = g20.itemId)
INNER JOIN item_group g21 ON g1.itemId = g21.itemId)
INNER JOIN item_group g22 ON g1.itemId = g22.itemId)
INNER JOIN item_group g23 ON g1.itemId = g23.itemId)
INNER JOIN item_group g24 ON g1.itemId = g24.itemId)
INNER JOIN item_group g25 ON g1.itemId = g25.itemId)
INNER JOIN item_group g26 ON g1.itemId = g26.itemId)
INNER JOIN item_group g27 ON g1.itemId = g27.itemId)
INNER JOIN item_group g28 ON g1.itemId = g28.itemId)
INNER JOIN item_group g29 ON g1.itemId = g29.itemId)
INNER JOIN item_group g30 ON g1.itemId = g30.itemId)
INNER JOIN item_group g31 ON g1.itemId = g31.itemId)
INNER JOIN item_group g32 ON g1.itemId = g32.itemId)
INNER JOIN item_group g33 ON g1.itemId = g33.itemId)
INNER JOIN item_group g34 ON g1.itemId = g34.itemId)
INNER JOIN item_group g35 ON g1.itemId = g35.itemId)
INNER JOIN item_group g36 ON g1.itemId = g36.itemId)
INNER JOIN item_group g37 ON g1.itemId = g37.itemId)
INNER JOIN item_group g38 ON g1.itemId = g38.itemId)
INNER JOIN item_group g39 ON g1.itemId = g39.itemId)
INNER JOIN item_group g40 ON g1.itemId = g40.itemId)
WHERE g1.groupId='1' AND g2.groupId='2' AND g3.groupId='3' AND g4.groupId='4' AND g5.groupId='5' AND g6.groupId='6' AND g7.groupId='7' AND g8.groupId='8' AND g9.groupId='9' AND g10.groupId='10' AND g11.groupId='11' AND g12.groupId='12' AND g13.groupId='13' AND g14.groupId='14' AND g15.groupId='15' AND g16.groupId='16' AND g17.groupId='17' AND g18.groupId='18' AND g19.groupId='19' AND g20.groupId='20' AND g21.groupId='21' AND g22.groupId='22' AND g23.groupId='23' AND g24.groupId='24' AND g25.groupId='25' AND g26.groupId='26' AND g27.groupId='27' AND g28.groupId='28' AND g29.groupId='29' AND g30.groupId='30' AND g31.groupId='31' AND g32.groupId='32' AND g33.groupId='33' AND g34.groupId='34' AND g35.groupId='35' AND g36.groupId='36' AND g37.groupId='37' AND g38.groupId='38' AND g39.groupId='39' AND g40.groupId='40'

最佳答案

您可以通过使用 INNER JOIN 来实现这一点。没有理由嵌套这些语句。

您的示例案例的适当查询的任何示例都是:

SELECT g1.itemId 
FROM (( item_group g1 
        INNER JOIN item_group g2 ON g1.itemId = g2.itemId)
        INNER JOIN item_group g3 ON g1.itemId = g3.itemId) 
WHERE g1.groupId='31' AND g2.groupId='24' AND g3.groupId='35'

我已经在一个包含三列 (id, itemId, groupId) 的简单表格上对此进行了测试,它可以正常工作。很容易将这种语句放入循环中,并且没有最大连接数。

为了加快运行速度,您应该为 item_group 表中的 itemId 列建立索引。

您可以使用以下 SQL 语句执行此操作:

ALTER TABLE item_group ADD INDEX ( itemId )

关于php - 在 MySQL 中实现 SQL INTERSECT 时嵌套级别太高,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11572110/

相关文章:

php - 如何为游戏实现库存系统?

php - MySQL 不同内连接

php - 如何在 Phalcon\Http\Request 中使用过滤器

javascript - 如何在codeigniter中的ajax之后仅加载指定的div

mysql - 调试套件显示重复的查询

mysql - 是否可以在不知道 JOIN 在哪一列上完成的情况下进行 JOIN?

PHP 在同一连接上调用第二个 MySQL 存储过程或查询?

php - 具有多表关系的 Yii 作用域

php - 如何在 Yii 中使用 Bootstrap ?

php - 在非对象上调用成员函数 saveAs() [Yii 2]