背景
我有一个在RDS上运行的Postgres 11数据库。我有两个表orders
和items
,如下所示:
CREATE TABLE schema.orders (
order_number TEXT,
order_date TIMESTAMPTZ,
sales_channel_name TEXT
);
CREATE TABLE schema.items (
order_number TEXT REFERENCES schema.orders(order_number),
key TEXT
quantity INT
);
我需要创建一个报告,在两个单独的列中显示行项目的count with列key
中的一些字符串,without列key
中的一些字符串],按关联的订单日期的日期分组。
所需的输出示例如下:
day | double_items_count | normal_items_count
-----------------------------------------------------------------------------------------------
2020-04-09 00:00:00 | 22 | 13
每个所需的列都可以定义为以下查询之一:
SELECT
date_trunc('day', o.order_date AT TIME ZONE 'America/Los_Angeles') AS day,
2*(count(*)) AS double_items_count
FROM
schema.items i
INNER JOIN
schema.orders o
ON i.order_number = o.order_number
WHERE
i.key ILIKE '%some_string%'
AND o.sales_channel_name = 'foo_sales_channel'
GROUP BY day
ORDER BY day DESC
;
SELECT
date_trunc('day', o.order_date AT TIME ZONE 'America/Los_Angeles') AS day,
count(*) AS normal_items_count
FROM
schema.items
INNER JOIN
schema.orders_new o
ON i.order_number = o.order_number
WHERE
i.key NOT ILIKE '%some_string%'
AND o.sales_channel_name = 'foo_sales_channel'
GROUP BY day
ORDER BY day DESC
;
我还有一个视图schema.items_from_channel
,该视图仅返回我感兴趣的那些记录:
CREATE VIEW schema.items_from_channel AS (
SELECT
date_trunc('day', o.date at time zone 'America/Los_Angeles') as day,
o.order_number,
i.key,
o.sales_channel
FROM
schema.orders o
INNER JOIN
schema.items i
ON
o.order_number = i.order_number
WHERE o.sales_channel = "foo_sales_channel"
ORDER BY day DESC
);
问题
通常,我将通过针对视图的直接查询或将上述两个查询结合在一起来处理此类问题。
但是,由于所需的列取决于互斥的WHERE条件,我不知道如何构造一个会同时产生这两个查询的查询(例如,带有子查询)。
由于这两个查询除day
之外均不共享其他任何键,因此我无法弄清楚如何以产生合理结果的方式来连接它们[在day
上连接,这对我来说很有意义,会产生虚数]。
UNION不会产生所需的结果,因为它会返回所有所需的数据,但不会保留所需的列格式。
我很困惑。如何生成所需的报告?在一天中的大部分时间里,我一直在搜索和梳理相关的SE网站,但并未提出解决方案。所有指导深表感谢!
具有以下数据:
select * from orders;
order_number | order_date | sales_channel_name
--------------+---------------------+--------------------
1 | 2020-04-09 01:00:00 | foo_sales_channel
2 | 2020-04-09 02:00:00 | foo_sales_channel
3 | 2020-04-09 03:00:00 | foo_sales_channel
4 | 2020-04-09 04:00:00 | foo_sales_channel
(4 rows)
select * from items;
id | key | order_number
----+----------------+--------------
1 | some_string | 1
2 | some_string | 2
3 | another_string | 3
4 | another_string | 4
(4 rows)
SELECT
date_trunc('day', o.order_date AT TIME ZONE 'America/Los_Angeles') AS day,
2*(count(*)) AS double_items_count
FROM
items i
INNER JOIN
orders o
ON i.order_number = o.order_number
WHERE
i.key ILIKE '%some_string%'
AND o.sales_channel_name = 'foo_sales_channel'
GROUP BY day
ORDER BY day DESC;
day | double_items_count
------------------------+--------------------
2020-04-09 00:00:00+02 | 4
(1 row)
SELECT
date_trunc('day', o.order_date AT TIME ZONE 'America/Los_Angeles') AS day,
count(*) AS normal_items_count
FROM
items i
INNER JOIN
orders o
ON i.order_number = o.order_number
WHERE
i.key NOT ILIKE '%some_string%'
AND o.sales_channel_name = 'foo_sales_channel'
GROUP BY day
ORDER BY day DESC
;
day | normal_items_count
------------------------+--------------------
2020-04-09 00:00:00+02 | 2
(1 row)
这里是解决方法:
SELECT
date_trunc('day', o.order_date AT TIME ZONE 'America/Los_Angeles') AS day,
2*count(*) FILTER (WHERE i.key ILIKE '%some_string%') AS double_items_count,
count(*) FILTER (WHERE i.key NOT ILIKE '%some_string%') AS normal_items_count
FROM
items i
INNER JOIN
orders o
ON i.order_number = o.order_number
WHERE
o.sales_channel_name = 'foo_sales_channel'
GROUP BY day
ORDER BY day DESC
;
day | double_items_count | normal_items_count
------------------------+--------------------+--------------------
2020-04-09 00:00:00+02 | 4 | 2
(1 row)