来自 CTE 的变量的无效操作错误
Invalid operation error with variables from CTE
CREATE TABLE customers (
id SERIAL PRIMARY KEY,
order_date DATE,
customer VARCHAR(255)
);
INSERT INTO customers
(order_date, customer)
VALUES
('2020-04-10', 'user_01'),
('2020-04-15', 'user_02'),
('2020-05-18', 'user_03'),
('2020-05-26', 'user_04'),
('2020-06-03', 'user_05'),
('2020-06-05', 'user_06'),
('2020-06-24', 'user_07');
我每月使用此查询提取用户数:
SELECT
c.customer
FROM customers c
WHERE c.order_date BETWEEN '2020-06-01' AND '2020-06-30'
这个查询没有任何问题。
现在我想使用日期作为变量,因此切换到:
WITH time_variables AS
(SELECT
'2020-06-01'::date AS start_date,
'2020-06-30'::date AS end_date)
SELECT
c.customer
FROM customers c
WHERE c.order_date BETWEEN (SELECT start_date FROM time_variables) AND (SELECT end_date FROM time_variables)
但是,当我 运行 这个查询时,我得到错误:
Invalid operation: This type of correlated subquery pattern is not supported due to internal error;
您知道 amazon-redshift
中为什么会出现此错误吗?
还有其他方法可以将日期用作变量吗?
要使用变量,您可以使用 DECLARE
DECLARE @StartDate DATE = Datefromparts(2020,06,01)
DECLARE @EndDate DATE= Datefromparts(2020,06,30)
SELECT
c.customer
FROM customers c
WHERE c.order_date BETWEEN @StartDate AND @EndDate
它可以使用 join
吗?
WITH time_variables AS (
SELECT '2020-06-01'::date AS start_date, '2020-06-30'::date AS end_date
)
SELECT c.customer
FROM customers c JOIN
time_variables tv
ON c.order_date BETWEEN tv.start_date AND tv.end_date;
发生这种情况是因为您编写的查询使用了一个相关的子查询,即 SELECT 在另一个 SELECT 的子句中(例如 WHERE 子句中的 SELECT ) 可以(可能)为外部 SELECT 的每一行解析为不同的值。在您的情况下,您的 CTE 只有一行,因此只能生成相同的值,但查询结构不需要这样做。 Redshift 不支持相关子查询结构 b/c 解决海量数据上的这些相关性变得非常昂贵(因此速度很慢)。
解决更改查询以使用 JOIN。像这样:
WITH time_variables AS
(SELECT
'2020-06-01'::date AS start_date,
'2020-06-30'::date AS end_date)
SELECT
c.customer
FROM customers c
CROSS JOIN time_variables v
WHERE c.order_date BETWEEN v.start_date AND v.end_date
这只是将 CTE 的一行连接到 customer 中的每一行。现在很清楚开始和结束日期是如何与 customer 中的数据相结合的。但是,如果您希望将变量放入 SQL 中,则有更好的方法不包括创建新的表结构。
CREATE TABLE customers (
id SERIAL PRIMARY KEY,
order_date DATE,
customer VARCHAR(255)
);
INSERT INTO customers
(order_date, customer)
VALUES
('2020-04-10', 'user_01'),
('2020-04-15', 'user_02'),
('2020-05-18', 'user_03'),
('2020-05-26', 'user_04'),
('2020-06-03', 'user_05'),
('2020-06-05', 'user_06'),
('2020-06-24', 'user_07');
我每月使用此查询提取用户数:
SELECT
c.customer
FROM customers c
WHERE c.order_date BETWEEN '2020-06-01' AND '2020-06-30'
这个查询没有任何问题。
现在我想使用日期作为变量,因此切换到:
WITH time_variables AS
(SELECT
'2020-06-01'::date AS start_date,
'2020-06-30'::date AS end_date)
SELECT
c.customer
FROM customers c
WHERE c.order_date BETWEEN (SELECT start_date FROM time_variables) AND (SELECT end_date FROM time_variables)
但是,当我 运行 这个查询时,我得到错误:
Invalid operation: This type of correlated subquery pattern is not supported due to internal error;
您知道 amazon-redshift
中为什么会出现此错误吗?
还有其他方法可以将日期用作变量吗?
要使用变量,您可以使用 DECLARE
DECLARE @StartDate DATE = Datefromparts(2020,06,01)
DECLARE @EndDate DATE= Datefromparts(2020,06,30)
SELECT
c.customer
FROM customers c
WHERE c.order_date BETWEEN @StartDate AND @EndDate
它可以使用 join
吗?
WITH time_variables AS (
SELECT '2020-06-01'::date AS start_date, '2020-06-30'::date AS end_date
)
SELECT c.customer
FROM customers c JOIN
time_variables tv
ON c.order_date BETWEEN tv.start_date AND tv.end_date;
发生这种情况是因为您编写的查询使用了一个相关的子查询,即 SELECT 在另一个 SELECT 的子句中(例如 WHERE 子句中的 SELECT ) 可以(可能)为外部 SELECT 的每一行解析为不同的值。在您的情况下,您的 CTE 只有一行,因此只能生成相同的值,但查询结构不需要这样做。 Redshift 不支持相关子查询结构 b/c 解决海量数据上的这些相关性变得非常昂贵(因此速度很慢)。
解决更改查询以使用 JOIN。像这样:
WITH time_variables AS
(SELECT
'2020-06-01'::date AS start_date,
'2020-06-30'::date AS end_date)
SELECT
c.customer
FROM customers c
CROSS JOIN time_variables v
WHERE c.order_date BETWEEN v.start_date AND v.end_date
这只是将 CTE 的一行连接到 customer 中的每一行。现在很清楚开始和结束日期是如何与 customer 中的数据相结合的。但是,如果您希望将变量放入 SQL 中,则有更好的方法不包括创建新的表结构。