合并来自相同 table 的 2 select 个查询

Joining 2 select queries from the same table

我有 两个 SQL 查询 来自同一个 table 如下。

Query1 -> select * from (select (start_date::text), (end_date::text), count("NEW") "NEW" from table_name where refnum in (select refnum from table_name where start_date in (SELECT start_date FROM table_name ORDER BY ID DESC LIMIT 1)) and "NEW">0 group by start_date, end_date order by end_date DESC limit 10) top_10 order by end_date ASC

Query2 -> select * from (select (start_date::text), (end_date::text), count("DELETED") "DELETED" from table_name where refnum in (select refnum from table_name where start_date in (SELECT start_date FROM table_name ORDER BY ID DESC LIMIT 1)) and "DELETED">0 group by start_date, end_date order by end_date DESC limit 10) top_10 order by end_date ASC

请建议一个最终查询以合并这两个子查询,从而产生一个 table

我想要最终的 table 包含列 start_date、end_date、NEW、DELETED

您可以使用 FULL JOIN,如:

select 
  coalesce(a.start_date, b.start_date) as start_date,
  coalesce(a.end_date, b.end_date) as end_date,
  a.new,
  b.deleted
from (
  -- query #1 here; exclude the ORDER BY clause
) a
full join (
  -- query #2 here; exclude the ORDER BY clause
) b on b.start_date = a.start_date and b.end_date = a.end_date
order by coalesce(a.end_date, b.end_date) ASC

您可以使用 union 运算符来堆叠表格:

select * from (select (start_date::text), (end_date::text), count("NEW") "NEW" from table_name where refnum in (select refnum from table_name where start_date in (SELECT start_date FROM table_name ORDER BY ID DESC LIMIT 1)) and "NEW">0 group by start_date, end_date order by end_date DESC limit 10) top_10 order by end_date ASC
UNION
select * from (select (start_date::text), (end_date::text), count("DELETED") "DELETED" from table_name where refnum in (select refnum from table_name where start_date in (SELECT start_date FROM table_name ORDER BY ID DESC LIMIT 1)) and "DELETED">0 group by start_date, end_date order by end_date DESC limit 10) top_10 order by end_date ASC

可以 使用 FULL [OUTER] JOIN 就像建议的那样。 但是 请注意,行与 NULL 值不匹配!如果您的结果行之一在 start_dateend_date 中包含 NULL,则不会合并“匹配”行。有变通办法,但我不打算这样做,因为我不希望它适用。此外,您的查询已经在 order by end_date DESC 中断,它首先对 NULL 值进行排序 - 可能是无意的 ...

无论哪种方式,如果您选择FULL JOIN,请使用USING子句:

SELECT start_date, end_date, a.new, b.deleted
FROM        ( <"top_10" subquery of Query1 here> ) a
FULL   JOIN ( <"top_10" subquery of Query2 here> ) b USING (start_date, end_date)  -- !
ORDER  BY end_date;

The manual:

A clause of the form USING ( a, b, ... ) is shorthand for ON left_table.a = right_table.a AND left_table.b = right_table.b .... Also, USING implies that only one of each pair of equivalent columns will be included in the join output, not both.

COALESCE(a.start_date, b.start_date) 等的需求消失了。更短、更简单、更快。

可能 甚至 NATURAL 加入:

SELECT start_date, end_date, a.new, b.deleted
FROM              a
NATURAL FULL JOIN b  -- !
ORDER   BY end_date;

The manual:

NATURAL is shorthand for a USING list that mentions all columns in the two tables that have matching names. If there are no common column names, NATURAL is equivalent to ON TRUE.

只有当您的子查询严格符合描述时才有意义,并且不会改变。我只看到极少数情况下这是可取的。

不过,这一切很可能是给猪涂口红。通常,您应该能够将两个查询合并为一个 - 简化(并修复)您当前拥有的内容。

向我们展示确切的 table 定义和确切的职位描述,我很可能可以用更好的查询来代替这句话。