MySQL 8 递归 CTE 为每个项目创建行
MySQL 8 Recursive CTE Create row for each item
我想从一个不存在的 table:
创建一个数据 return
+-------+--------+------------+
| type | name | expiration |
+-------+--------+------------+
| fruit | orange | 1999-12-31 |
| fruit | banana | 1999-12-31 |
| fruit | apple | 1999-12-31 |
| fruit | orange | 2000-01-01 |
| fruit | banana | 2000-01-01 |
| fruit | apple | 2000-01-01 |
+-------+--------+------------+
每个水果都有一行具有相同的日期。然后日期增加一天,并为该日期为每个水果创建一行。
到目前为止我有这个查询:
WITH RECURSIVE cte
AS (
SELECT
"fruit" as `type`
,"orange" as `name`
,"1999-12-31" as `expiration`
UNION ALL
SELECT
"fruit" as `type`
,"banana" as `name`
,date_add(`expiration`, INTERVAL 1 DAY) as `expiration`
FROM cte
WHERE `expiration` < "2000-01-01"
)
SELECT *
FROM cte
;
生成:
+-------+--------+------------+
| type | name | expiration |
+-------+--------+------------+
| fruit | orange | 1999-12-31 |
| fruit | banana | 2000-01-01 |
+-------+--------+------------+
我认为可以通过在具有水果名称的临时 fruit_list
table 中执行递归 CTE select 内部来解决该问题,但我不知道如何实现那个。
例子fruit_list
table:
CREATE TEMPORARY TABLE IF NOT EXISTS `fruit_list` (
`name` varchar(128) NOT NULL
) ENGINE = InnoDB;
INSERT INTO `fruit_list` VALUES
("orange")
,("banana")
,("apple")
;
我想用常规查询而不是过程来解决问题。可能吗?
解决方案的目的是有一个查询,可以 return 每个水果和日期范围的一些测试数据。
您可以通过一系列交叉连接来处理此问题:
SELECT
f.type,
n.name,
e.expiration
FROM (SELECT 'fruit' AS type) f
CROSS JOIN
(
SELECT 'orange' AS name UNION ALL
SELECT 'banana' UNION ALL
SELECT 'apple'
) n
CROSS JOIN
(
SELECT '1999-12-31' AS expiration UNION ALL
SELECT '2000-01-01'
) e
ORDER BY
f.type,
e.expiration,
n.name;
对于那些想使用临时 table 的人,这里是代码:
CREATE TEMPORARY TABLE IF NOT EXISTS `fruit_list` (
`name` varchar(128) NOT NULL
) ENGINE = InnoDB;
INSERT INTO `fruit_list` VALUES
("orange")
,("banana")
,("apple")
;
WITH RECURSIVE cte
AS (
SELECT
"1999-12-30" as `expiration`
UNION ALL
SELECT
date_add(`expiration`, INTERVAL 1 DAY) as `expiration`
FROM cte
WHERE `expiration` < "2000-01-02"
)
,cte1 as (
SELECT * FROM cte
CROSS JOIN `fruit_list`
)
SELECT
"fruit" as `type`
,`name`
,`expiration`
FROM cte1
ORDER BY
`expiration`
,`name`
;
结果:
+-------+--------+------------+
| type | name | expiration |
+-------+--------+------------+
| fruit | apple | 1999-12-30 |
| fruit | banana | 1999-12-30 |
| fruit | orange | 1999-12-30 |
| fruit | apple | 1999-12-31 |
| fruit | banana | 1999-12-31 |
| fruit | orange | 1999-12-31 |
| fruit | apple | 2000-01-01 |
| fruit | banana | 2000-01-01 |
| fruit | orange | 2000-01-01 |
| fruit | apple | 2000-01-02 |
| fruit | banana | 2000-01-02 |
| fruit | orange | 2000-01-02 |
+-------+--------+------------+
12 rows in set (0.00 sec)
我想从一个不存在的 table:
创建一个数据 return+-------+--------+------------+
| type | name | expiration |
+-------+--------+------------+
| fruit | orange | 1999-12-31 |
| fruit | banana | 1999-12-31 |
| fruit | apple | 1999-12-31 |
| fruit | orange | 2000-01-01 |
| fruit | banana | 2000-01-01 |
| fruit | apple | 2000-01-01 |
+-------+--------+------------+
每个水果都有一行具有相同的日期。然后日期增加一天,并为该日期为每个水果创建一行。
到目前为止我有这个查询:
WITH RECURSIVE cte
AS (
SELECT
"fruit" as `type`
,"orange" as `name`
,"1999-12-31" as `expiration`
UNION ALL
SELECT
"fruit" as `type`
,"banana" as `name`
,date_add(`expiration`, INTERVAL 1 DAY) as `expiration`
FROM cte
WHERE `expiration` < "2000-01-01"
)
SELECT *
FROM cte
;
生成:
+-------+--------+------------+
| type | name | expiration |
+-------+--------+------------+
| fruit | orange | 1999-12-31 |
| fruit | banana | 2000-01-01 |
+-------+--------+------------+
我认为可以通过在具有水果名称的临时 fruit_list
table 中执行递归 CTE select 内部来解决该问题,但我不知道如何实现那个。
例子fruit_list
table:
CREATE TEMPORARY TABLE IF NOT EXISTS `fruit_list` (
`name` varchar(128) NOT NULL
) ENGINE = InnoDB;
INSERT INTO `fruit_list` VALUES
("orange")
,("banana")
,("apple")
;
我想用常规查询而不是过程来解决问题。可能吗?
解决方案的目的是有一个查询,可以 return 每个水果和日期范围的一些测试数据。
您可以通过一系列交叉连接来处理此问题:
SELECT
f.type,
n.name,
e.expiration
FROM (SELECT 'fruit' AS type) f
CROSS JOIN
(
SELECT 'orange' AS name UNION ALL
SELECT 'banana' UNION ALL
SELECT 'apple'
) n
CROSS JOIN
(
SELECT '1999-12-31' AS expiration UNION ALL
SELECT '2000-01-01'
) e
ORDER BY
f.type,
e.expiration,
n.name;
对于那些想使用临时 table 的人,这里是代码:
CREATE TEMPORARY TABLE IF NOT EXISTS `fruit_list` (
`name` varchar(128) NOT NULL
) ENGINE = InnoDB;
INSERT INTO `fruit_list` VALUES
("orange")
,("banana")
,("apple")
;
WITH RECURSIVE cte
AS (
SELECT
"1999-12-30" as `expiration`
UNION ALL
SELECT
date_add(`expiration`, INTERVAL 1 DAY) as `expiration`
FROM cte
WHERE `expiration` < "2000-01-02"
)
,cte1 as (
SELECT * FROM cte
CROSS JOIN `fruit_list`
)
SELECT
"fruit" as `type`
,`name`
,`expiration`
FROM cte1
ORDER BY
`expiration`
,`name`
;
结果:
+-------+--------+------------+
| type | name | expiration |
+-------+--------+------------+
| fruit | apple | 1999-12-30 |
| fruit | banana | 1999-12-30 |
| fruit | orange | 1999-12-30 |
| fruit | apple | 1999-12-31 |
| fruit | banana | 1999-12-31 |
| fruit | orange | 1999-12-31 |
| fruit | apple | 2000-01-01 |
| fruit | banana | 2000-01-01 |
| fruit | orange | 2000-01-01 |
| fruit | apple | 2000-01-02 |
| fruit | banana | 2000-01-02 |
| fruit | orange | 2000-01-02 |
+-------+--------+------------+
12 rows in set (0.00 sec)