Php 根据多个类别动态匹配项目

Php 根据多个类别动态匹配项目,php,mysql,sql,database,pdo,Php,Mysql,Sql,Database,Pdo,鉴于下表: CREATE TABLE catalog_categories ( cat_id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, parent_id INTEGER UNSIGNED DEFAULT NULL, title VARCHAR(255) NOT NULL, valid TINYINT(1) UNSIGNED NOT NULL DEFAULT 1, PRIMARY KEY(cat_id), FOREIGN KEY

鉴于下表:

CREATE TABLE catalog_categories (
  cat_id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
  parent_id INTEGER UNSIGNED DEFAULT NULL,
  title VARCHAR(255) NOT NULL,
  valid TINYINT(1) UNSIGNED NOT NULL DEFAULT 1,

  PRIMARY KEY(cat_id),
  FOREIGN KEY (parent_id)
    REFERENCES catalog_categories(cat_id)
);

CREATE TABLE catalog_item_categories (
  item_id INTEGER UNSIGNED NOT NULL,
  cat_id INTEGER UNSIGNED NOT NULL,
  valid TINYINT(1) UNSIGNED NOT NULL DEFAULT 1,

  FOREIGN KEY (item_id)
    REFERENCES catalog_items(item_id),
  FOREIGN KEY (cat_id)
    REFERENCES catalog_categories(cat_id)
);
和多维数组作为输入,其中
key=>parent\u id,value=>cat\u id

["categories"]=>
array(2) {
  [1]=>
  array(2) {
    [0]=>
    string(1) "5"
    [1]=>
    string(1) "6"
  }
  [2]=>
  array(1) {
    [0]=>
    string(2) "12"
  }
}
我试图只选择与提供的类别匹配的项目

SELECT    a.item_id
FROM      catalog_items AS a
JOIN      catalog_item_categories AS b ON a.item_id = b.item_id
JOIN      catalog_categories AS c ON b.cat_id = c.cat_id AND c.parent_id = 1 AND c.cat_id IN ('5', '6')
JOIN      catalog_categories AS d ON b.cat_id = d.cat_id AND d.parent_id = 2 AND d.cat_id IN ('12')
WHERE     a.valid = TRUE
          AND b.valid = TRUE
          AND c.valid = TRUE
          AND d.valid = TRUE

这是我硬编码的尝试,但是有没有更好的方法,或者我如何动态地构建这个查询?如果我事先不知道会有多少个
父=>子
关系。

您可以通过聚合查询来实现这一点,聚合查询的构造可能更简单:

select cic.item_id
from catalog_item_categories cic
group by cic.item_id
where sum(cic.cat_id in (5, 6) and cic.valid = 1) > 0 and
      sum(cic.cat_id in (12) and cic.valid = 1) > 0;

考虑通过类别循环,使用动态PHP字符串构建SQL查询。当然,如果数组数据来自用户输入,请使用以下选项,而不是concateration:

$categories = [
    1 => array("5","6"),
    2 => array("12")
];

$sql = "SELECT a.item_id
        FROM   catalog_items AS a 
        JOIN   catalog_item_categories AS b ON a.item_id = b.item_id";            
$i = 1;
foreach($categories as $k=>$v){        
    $cats = implode(",", $v);      

    $sql = $sql."
        JOIN catalog_categories AS c$i ON b.cat_id = c$i.cat_id AND c$i.parent_id = $k 
             AND c$i.cat_id IN ($cats) AND c$i.valid = TRUE";    
    $i = $i + 1;
}

$sql = $sql.
       "\nWHERE a.valid = TRUE AND b.valid = TRUE";

echo $sql;
输出

选择一个项目\u id
从目录_项作为
在a.item\u id=b.item\u id上将目录\u item\u类别作为b连接
在b.cat_id=c1.cat_id和c1.parent_id=1上以c1的形式连接目录_类别
和c1.cat_id IN(5,6)和c1.valid=TRUE
在b.cat_id=c2.cat_id和c2.parent_id=2上以c2的形式加入目录_类别
和c2.cat_id IN(12)和c2.valid=TRUE
其中a.valid=TRUE和b.valid=TRUE

我没有
家长id
。你能提供样本数据和期望的结果吗?类别可以有子类别…我有点困惑。此解决方案不检查项目是否有效(您遗漏了
目录项目
),并且它忽略了用于将子项与其父类别关联的
父项id
。您还遗漏了
目录类别
,因此它不检查类别是否有效。