【问题标题】:Use output of one statement as input for another (recursively)使用一个语句的输出作为另一个语句的输入(递归)
【发布时间】:2022-01-18 09:01:17
【问题描述】:

product 表通过product.ext_category_id=categories.ext_idcategories 表相关联,但是ext_category_id 可能与categories 表中的1 级、2 级或3 级类别相关联。

我正在寻找一个 select 语句,它将选择 products 表中的所有产品以及从类别表中相应的级别 1 类别。

product.id product.product_name categories.name
1 Strawberries Fruit & Vegetable department
2 Bananas Fruit & Vegetable department
3 Potatoes Fruit & Vegetable department
4 Car Battery Automotive department
5 Chips Junk Food department

如果products 表中的产品与categories 表中的2 级或3 级类别相关联,则您需要使用categories.parent_id 搜索@987654334 中的categories.id 列@table 查找下一个类别,直到获得第 1 级类别。

我花了一天时间尝试使用各种方法来解决这个问题,例如 CASE 和带有 select 语句的子查询以及递归函数,但没有任何效果。示例 CASE sn-p -

SELECT
    product.id,
    product.product_name,
    CASE WHEN categories.level = '3' THEN (
           SELECT c2.name
           FROM categories c2
           WHERE c2.id = categories.parent_id )
    END AS level_2_cat_name
FROM product
    JOIN categories ON categories.ext_id = product.ext_category_id

示例product

id product_name ext_category_id
1 Strawberries 101
2 Bananas 102
3 Potatoes 103
4 Car Battery 104
5 Chips 105

示例categories

id ext_id name level parent_id
1001 101 Fruit 2 2000
1002 102 Fruit 2 2000
1003 103 Vegetables 2 2000
1004 104 Car Parts 3 2500
2001 209 Junk Food Department 1 Null

...

id ext_id name level parent_id
2000 205 Fruit & Vegetable department 1 Null
2000 205 Fruit & Vegetable department 1 Null
2000 205 Fruit & Vegetable department 1 Null
2500 309 Cars & Trucks 2 2002
2002 209 Automotive department 1 Null
2001 209 Junk Food department 1 Null

【问题讨论】:

  • 一种方法是先递归遍历类别表,导出对,然后将此结果与产品表连接。但是您也可以使用产品表来确定类别中的起始/根以开始遍历。
  • 感谢您的建议,不幸的是,我对您所建议的复杂查询还很陌生(至少对我来说似乎很复杂?)。有什么方法可以举个例子吗?

标签: sql postgresql


【解决方案1】:

这是一个使用递归 CTE 解决问题的示例。 这几乎可以处理任意数量的类别级别。

有几种方法可以做到这一点。

您的测试数据有一些错误。我已经为这次测试更正了它们。

注意:存在外连接,因为您的初始数据没有与 Chips 相关的匹配类别。如果没有丢失的数据,可以将其删除。我现在要删除它。

The fiddle

WITH RECURSIVE cte1 (id, name, cid, cname, level, parent_id) AS (
        SELECT p.id, p.product_name, c.id, c.name, level, parent_id
          FROM product     AS p
          JOIN categories  AS c
            ON p.ext_category_id = c.ext_id
         UNION ALL
        SELECT p.id, p.name, c.id AS cid, c.name AS cname, c.level, c.parent_id
          FROM cte1        AS p
          JOIN categories  AS c
            ON c.id = p.parent_id
     )
SELECT id, name, cname
  FROM cte1
 WHERE level = 1
 ORDER BY id
;

结果:

+------+--------------+------------------------------+
| id   | name         | cname                        |
+------+--------------+------------------------------+
|    1 | Strawberries | Fruit & Vegetable department |
|    2 | Bananas      | Fruit & Vegetable department |
|    3 | Potatoes     | Fruit & Vegetable department |
|    4 | Car Battery  | Automotive department        |
|    5 | Chips        | Junk Food Department         |
+------+--------------+------------------------------+

设置:

CREATE TABLE product (
    id               int
  , product_name     varchar(40)
  , ext_category_id  int
);

INSERT INTO product VALUES
  ( 1, 'Strawberries' , 101)
, ( 2, 'Bananas'      , 102)
, ( 3, 'Potatoes'     , 103)
, ( 4, 'Car Battery'  , 104)
, ( 5, 'Chips'        , 105)
;

CREATE TABLE categories (
    id           int
  , ext_id       int
  , name         varchar(40)
  , level        int
  , parent_id    int
);

-- id   ext_id  name    level   parent_id
INSERT INTO categories VALUES
  (1001, 101, 'Fruit'                , 2, 2000)
, (1002, 102, 'Fruit'                , 2, 2000)
, (1003, 103, 'Vegetables'           , 2, 2000)
, (1004, 104, 'Car Parts'            , 3, 2500)
, (1005, 105, 'FoodParts'            , 2, 2001)
, (2001, 209, 'Junk Food Department' , 1, Null)
, (2000, 205, 'Fruit & Vegetable department', 1, Null)
, (2500, 309, 'Cars & Trucks'               , 2, 2002)
, (2002, 209, 'Automotive department'       , 1, Null)
;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-01
    • 2012-10-06
    • 1970-01-01
    • 1970-01-01
    • 2017-02-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多