动态匹配多个类别的项目

时间:2017-05-25 15:34:47

标签: 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 (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_id, value => cat_ids

["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

这是我的硬编码尝试,但是有更好的方法,或者我将如何动态构建此查询?如果我提前知道会有多少parent => child个关系。

2 个答案:

答案 0 :(得分:1)

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

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

输出

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 c1 ON b.cat_id = c1.cat_id AND c1.parent_id = 1 
     AND c1.cat_id IN (5,6) AND c1.valid = TRUE
JOIN catalog_categories AS c2 ON b.cat_id = c2.cat_id AND c2.parent_id = 2 
     AND c2.cat_id IN (12) AND c2.valid = TRUE
WHERE a.valid = TRUE AND b.valid = TRUE

答案 1 :(得分:0)

您可以使用聚合查询来完成此操作,这可能更容易构建:

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;