我有这样的桌子。
Categories (id[PK], name, parentid);
Product(prid[PK], product_name, product_price);
ProductCategories(id[PK], prid[FK], catid[FK]);
一个产品属于多个类别。
我有一个场景,我将从用户那里获取一个 catid,并且我必须获取属于该类别的产品。同时,我还必须获取该类别的子类别(如果有)并获取子类别的产品。 获取类别及其子类别是一项简单的任务 - 通过自连接。
但我必须检查那些类别是否已标记产品。 (意味着如果该类别/子类别下没有标记产品,则忽略该类别)
例如
Automobile (0 products)
Two Wheelers (0 products)
Mopeds (2 products)
Bikes (5 products)
Sport Bikes (0 products)
Four Wheelers (0 products)
Convertible (0 products)
SUV (4 products)
TUV (2 products)
Tyres (0 products)
所以我想要这样的结果(那些类别/子类别没有我必须删除的产品)。
Automobile
Two Wheelers
Mopeds
Bikes
Four Wheelers
SUV
TUV
我通过循环类别来完成这件事。我可以在单个查询中完成此操作吗?
一些代码:
$rows = (new \yii\db\Query())
->select(["COUNT( * ) AS prodcount",'c1.parentid', "GROUP_CONCAT(c1.id, ':', c1.name) as catid"])
->from('category c1')
->join('inner join','category c2','c1.id=c2.id')
->where(['not in','c1.parentid','0'])
->andWhere(['!=','c1.parentid',1])
->andWhere(array('c1.status'=>1))
->andWhere(array('c2.status'=>1))
->groupBy('c1.parentid')
->orderBy('prodcount DESC')
->all();
$result=array();
foreach ($rows as $r)
{
$cats= explode(":",$r['catid']);
if( $this->hasProducts($cats[0]))
{
if($r['parentid']!=1)
{
$pnm= \backend\models\Category::find()->select('name')->where(['id'=>$r['parentid']])->one();
$result['parent']=$r['parentid'].":".$pnm['name'];
}
else{
$result['parent']=$r['parentid'].":".'Main';
}
$result['catid']=$r['catid'];
$this->cat[$result['parent']]=$result['catid'];
}
}
我在这里检查该类别是否至少有一个产品?
public function hasProducts($catid)
{
$hasProducts=false;
$allCats= array();
$allCats = $this->getAllChildren($catid);
if($allCats!== NULL && !empty($allCats) && sizeOf($allCats)>0)
{
$cats = implode(",",$allCats);
$prodcatquery = (new \yii\db\Query())
->from('product_categories pc')
->where("pc.catid in ($cats)");
$products= $prodcatquery->all();
if (sizeOf($products)>0)
{
$hasProducts=true;
}
}
return $hasProducts;
}
获取该类别的所有子类别
public function getAllChildren($catid)
{
$cats=$catid;
$allcats=array();
$currentcats=array();
array_push($allcats, $catid);
$intialquery = (new \yii\db\Query())
->select(['id'])
->from('category')
->where("parentid in ($cats)");
$catidreturned = $intialquery->all();
$i=0;
while(sizeOf($catidreturned ) > 0 && $i <=3 )
{
foreach ($catidreturned as $categoryid )
{
array_push( $allcats,$categoryid['id']);
array_push( $currentcats,$categoryid['id']);
}
$cats= implode(',', $currentcats);
$intialquery1 = (new \yii\db\Query())
->select(['id'])
->from('category')
->where("parentid in ($cats)");
$catidreturned = $intialquery1->all();
$currentcats=array();
$i++;
}
return $allcats;
}
问题:我通过循环类别来完成这件事。我可以在单个查询中完成此操作吗?
从类别=1的类别或子类别中选择产品(从子类别中选择子类别,其中id=1)
根据您的表格进行修改
SELECT *
FROM (
SELECT
CASE
WHEN c2_id IS NULL THEN 1
WHEN c3_id IS NULL THEN 2
ELSE 3
END AS level,
CASE
WHEN c2_id IS NULL THEN c1_id
WHEN c3_id IS NULL THEN c2_id
ELSE c3_id
END AS id,
CASE
WHEN c2_id IS NULL THEN c1_name
WHEN c3_id IS NULL THEN c2_name
ELSE c3_name
END AS name,
CASE
WHEN c2_id IS NULL THEN c1_own_products_count
WHEN c3_id IS NULL THEN c2_own_products_count
ELSE c3_own_products_count
END AS own_products_count,
CASE
WHEN c2_id IS NULL THEN c1_nested_products_count
WHEN c3_id IS NULL THEN c2_nested_products_count
ELSE c3_nested_products_count
END AS nested_products_count
FROM (
SELECT
-- Level 1
c1.id AS c1_id,
c1.name AS c1_name,
COUNT(DISTINCT c1p.id) AS c1_own_products_count,
COUNT(DISTINCT c1p.id)+
COUNT(DISTINCT c2p.id)+
COUNT(DISTINCT c3p.id) AS c1_nested_products_count,
-- Level 2
c2.id AS c2_id,
c2.name AS c2_name,
COUNT(DISTINCT c2p.id) AS c2_own_products_count,
COUNT(DISTINCT c2p.id)+
COUNT(DISTINCT c3p.id) AS c2_nested_products_count,
-- Level 3
c3.id AS c3_id,
c3.name AS c3_name,
COUNT(DISTINCT c3p.id) AS c3_own_products_count,
COUNT(DISTINCT c3p.id) AS c3_nested_products_count
FROM Categories c1
LEFT JOIN Categories c2 ON(c2.parentid = c1.id)
LEFT JOIN Categories c3 ON(c3.parentid = c2.id)
LEFT JOIN ProductCategories c1p ON(c1p.catid=c1.id)
LEFT JOIN ProductCategories c2p ON(c2p.catid=c2.id)
LEFT JOIN ProductCategories c3p ON(c3p.catid=c3.id)
GROUP BY c1.id, c2.id, c3.id
WITH ROLLUP -- This will generate subtotals for level 1 and 2
) AS tree
WHERE c1_id IS NOT NULL -- Skip the row with total product count.
) AS list
WHERE nested_products_count = 0 -- Skip categories with no nested products
SELECT DISTINCT products.*, (select GROUP_CONCAT(categorys.id,'-',categories.tenDanhMuc) fromcategory__product 内连接类别 on id =category_id where product_id = products.id) 作为category_name 来自产品 INNER JOIN 类别__产品 类别__product.product_id = products.id WHERE 类别__product.category_id = 1;
您可以使用属性:DISTINCT、GROUP_CONCAT 和分割结果