【问题标题】:Joining 2 select queries from the same table加入来自同一个表的 2 个选择查询
【发布时间】:2020-07-03 21:41:11
【问题描述】:

我有来自同一个表的两个 SQL 查询,如下所示。

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

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

我想要包含列 start_date、end_date、NEW、DELETED

的最终表格

【问题讨论】:

  • 您想使用哪些列加入? start_dateend_date?
  • 是的,开始日期和结束日期
  • 很多更好的解决方案。您能否提供您的 Postgres 版本和表定义(CREATE TABLE table_name .. 语句),显示数据类型和约束。
  • @ErwinBrandstetter 9.x 版
  • 在 Postgres 10 之前,主要的 Postgres 版本包括第二个数字。见:postgresql.org/support/versioning 所以 9.6?还请提供查询应该实现的描述。那里有几段看起来可能存在误解的 SQL。

标签: sql postgresql join subquery


【解决方案1】:

您可以使用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

【讨论】:

    【解决方案2】:

    可以使用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:

    USING ( a, b, ... ) 形式的子句是ON left_table.a = right_table.a AND left_table.b = right_table.b .... 的简写 此外,USING 意味着每对等效列中只有一个 将包含在连接输出中,而不是两者都包含。

    不再需要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:

    NATURALUSING 列表的简写,它提到了 两个具有匹配名称的表。如果没有公共列 名称,NATURAL 等价于 ON TRUE

    仅当您的子查询严格符合描述时才有意义,并且不会改变。我只见过极少数情况下建议这样做。

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

    向我们展示准确的表定义和准确的职位描述,我很有可能可以用更好的查询替换这句话。

    【讨论】:

      【解决方案3】:

      您可以使用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
      

      【讨论】:

      • 这是我的第一次尝试......它会抛出“错误:在“UNION”处或附近出现语法错误”
      • 您是否尝试删除订单并将其放在整个查询之后?
      猜你喜欢
      • 2013-01-16
      • 2016-11-10
      • 1970-01-01
      • 2017-09-28
      • 1970-01-01
      • 2012-10-15
      • 2021-10-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多