来自 CTE 的变量的无效操作错误

Invalid operation error with variables from CTE

DB-Fiddle

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 中,则有更好的方法不包括创建新的表结构。