MariaDB SQL递归查询作为子查询

qv7cva1a  于 2023-03-08  发布在  其他
关注(0)|答案(1)|浏览(267)

我有一个数据结构,其中:

  • 供应商有一个偶然事件(多个供应商可以使用同一个偶然事件,这就是为什么它是不同的表)
  • 特遣队也可以有父特遣队(深度不限)
  • 如果供应链中的一个特遣队什么都没有留下,则供应商被视为没有留下特遣队
  • 如果余额为NULL,则没有设置限额,并计为或有可用
  • 遗憾的是,重新设计数据结构来解决这个问题是不可能的。*

递归部分和所有连续可用的规则可以如下编码:

WITH RECURSIVE rec_contigents as (
  SELECT 
    id, IFNULL(daily_remain, 1) > 0 as row_contigent, parent_id
  FROM contingents
  Where id = 1
  UNION
  select pc.id, IFNULL(pc.daily_remain, 1) > 0 as row_contigent, pc.parent_id
  FROM contingents pc, rec_contigents c
  where pc.id = c.parent_id)
select id, SUM(row_contigent) = count(row_contigent) as contigent from rec_contigents;

我可以很容易地得到我所有的供应商,然后一个接一个地查询上面的内容。不过,我想让我们减少数据库调用,并使用上面的内容作为子查询。(简化,实际上它包含多个关于供应商的JOINS和一些where子句)

SELECT
  v.vendor_id,
  (
        WITH RECURSIVE rec_contigents as (
            SELECT 
            id, IFNULL(daily_remain, 1) > 0 as row_contigent, parent_id
            FROM contingents
            Where id = v.contingent_id
            UNION
            select pc.id, IFNULL(pc.daily_remain, 1) > 0 as row_contigent, pc.parent_id
            FROM contingents pc, rec_contigents c
            where pc.id = c.parent_id
        )
        select SUM(row_contigent) = count(row_contigent) as contigent from rec_contigents
    ) as contingent_left
  FROM vendors AS v

这将导致以下错误:Unknown column 'v.contingent_id' in 'where clause'.
以下示例数据:

CREATE TABLE `contingents` (
  `id` int(11) NOT NULL,
  `daily` int(11) DEFAULT NULL,
  `daily_remain` int(11) DEFAULT NULL,
  `parent_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) 

INSERT INTO `contingents` (`id`, `daily`, `daily_remain`, `parent_id`)
VALUES
    (1,10,10,NULL),
    (2,10,5,1),
    (3,10,NULL,2),
    (4,10,0,NULL),
    (5,10,10,4);

CREATE TABLE `vendors` (
  `id` int(11) NOT NULL,
  `contingent_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
)

INSERT INTO `vendors` (`id`, `contingent_id`)
VALUES
    (1,3),
    (2,5);

预期成果:

+-----------+-----------------+
| vendor_id | contingent_left |
+-----------+-----------------+
|     1     |        1        |
|     2     |        0        |
+-----------+-----------------+

供应商1:有特遣队,因为他和他的父母都有大陆剩余(或有无限特遣队)。供应商2:没有洲,因为其父级没有洲了。
我已经看了下面的帖子,虽然这些解决方案不适合我:

  • Mysql Mariadb recursive query-在递归表上使用JOIN,但我不能使用它,因为我首先需要对它求和
  • SQL Recursive query as subquery-表示删除导致数据过多的Where id = v.contingent_id和导致错误结果的select SUM(row_contigent) = count(row_contigent) as contigent from rec_contigents
odopli94

odopli941#

WITH RECURSIVE
cte AS (
  SELECT ven.id,
         CASE WHEN con.daily_remain = 0 THEN 1 ELSE 0 END have_zero,
         con.parent_id
  FROM vendors ven
  JOIN contingents con ON ven.contingent_id = con.id
  UNION ALL
  SELECT cte.id, 
         CASE WHEN con.daily_remain = 0 THEN 1 ELSE 0 END,
         con.parent_id
  FROM cte
  JOIN contingents con ON cte.parent_id = con.id
  WHERE NOT have_zero
)
-- SELECT * FROM cte
SELECT id, NOT MAX(have_zero) contingent_left
FROM cte
GROUP BY id

https://dbfiddle.uk/wVJDsp4V

相关问题