递归选择和连接相关表

时间:2016-09-05 03:59:26

标签: sql database postgresql recursive-query

CREATE TABLE IF NOT EXISTS "product_category"(
  "id" SERIAL NOT NULL,
  "parent_id" integer DEFAULT NULL,
  "name" varchar DEFAULT NULL,
  PRIMARY KEY ("id")
);


CREATE TABLE IF NOT EXISTS "product"(
  "id" SERIAL NOT NULL,
  "product_category_id" integer DEFAULT NULL,
  PRIMARY KEY ("id")
);

我有两张上面的表,
product_category是层次结构,
product.product_category_id fk product_category.id

如何选择特定product_category id下的所有产品,

e.g
如果输入product_category 1,
输出 - >产品:1,产品:2

如果输入product_category 2
输出 - >产品:2

product_category
id | parent_id | name
1  |           | parent
2  | 1         | child
3  | 2         | child child


product
id | product_category_id
1  | 1
2  | 3

查询

像这样?但这只返回product_category列表....我想要产品列表

WITH RECURSIVE pc AS (
  SELECT pc.id AS id
    FROM product_category pc

    LEFT JOIN product p ON p.product_category_id = pc.id

    WHERE id = $1 

  UNION ALL

  SELECT child.id
    FROM product_category AS child

    LEFT JOIN product p ON p.product_category_id = child.id

    JOIN pc ON pc.id = child.parent_id 
)
SELECT * FROM product_category WHERE id IN (SELECT * FROM pc)

2 个答案:

答案 0 :(得分:2)

您应首先建立类别列表,然后将其加入产品。

WITH RECURSIVE pc AS (
  SELECT id
  FROM product_category 
  WHERE id = $id

  UNION ALL

  SELECT child.id
    FROM product_category AS child
    JOIN pc ON pc.id = child.parent_id 
)
SELECT pr.*
FROM product pr
  JOIN pc on pr.product_category_id = pc.id
;

答案 1 :(得分:1)

注意:我的系统上没有安装postgresql,所以我基于概念进行讨论。我没有看到你在哪里定义了外键约束......我仍假设你已经这样做了。我还没有检查CTE /公用表表达式的正确性( - 基本上是SQL的递归部分)。 假设CTE正确 -

如何更换

SELECT * FROM product_category WHERE id IN (SELECT * FROM pc)

SELECT * FROM product WHERE product_category_id IN (SELECT * FROM pc)

接下来我要检查CTE的正确性。

显然以下情况应该有效:

;
WITH RECURSIVE pc AS (
    SELECT pc.id AS id
    FROM 
    product_category pc
    LEFT JOIN product p 
    ON p.product_category_id = pc.id
    WHERE pc.id = <Your product category id of interest>
    UNION ALL
    SELECT child.id
    FROM 
    product_category AS child
    LEFT JOIN product p 
    ON p.product_category_id = child.id
    JOIN pc 
    ON pc.id = child.parent_id
)
SELECT id as product_id FROM product WHERE product_category_id 
IN (
   SELECT * FROM pc
);