如何在单个查询中获取拥有产品的嵌套类别?

问题描述 投票:0回答:3

我有这样的桌子。

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

问题:我通过循环类别来完成这件事。我可以在单个查询中完成此操作吗?

php mysql sql yii2
3个回答
0
投票

从类别=1的类别或子类别中选择产品(从子类别中选择子类别,其中id=1)

根据您的表格进行修改


0
投票
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

0
投票

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 和分割结果

© www.soinside.com 2019 - 2024. All rights reserved.