【问题标题】:Select query with join between two tables选择在两个表之间连接的查询
【发布时间】:2014-12-08 22:23:11
【问题描述】:

我必须以年度格式获取结果,但以下查询返回意外输出:

    SELECT EXTRACT (YEAR FROM Tab_1.DATE_STMP), COUNT (Tab_1.DATE_STMP), 

    EXTRACT (YEAR FROM Tab_2.DATE_STMP), COUNT (Tab_2.DATE_STMP) FROM  

    EMP_1 Tab_1 FULL OUTER JOIN EMP_2@LINK Tab_2  

    ON EXTRACT(YEAR FROM Tab_1.DATE_STMP)= EXTRACT(YEAR FROM Tab_2.DATE_STMP)  

    GROUP BY EXTRACT (YEAR FROM Tab_1.DATE_STMP),

    EXTRACT (YEAR FROM Tab_2.DATE_STMP);

预期输出:

2014    40  2014    20

实际输出:

2014    800 2014    800

我的长 plsql 解决方案是迭代 DATE 值并分别查询 Count:

--PL/SQL
OPEN cur FOR 'SELECT DATE_STMP FROM EMP_1@LINK1 UNION SELECT DATE_STMP FROM EMP_2@LINK2'
FETCH cur INTO v_datVar;
...
EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM EMP_1 WHERE EXTRACT (YEAR FROM DATE_STMP)='||v_datVar INTO v_Total2;
EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM EMP_2 WHERE EXTRACT (YEAR FROM DATE_STMP)='||v_datVar INTO v_Total2;
...
--PRINT VALUES HERE

问题。

是否有单个选择查询来获取此输出? (使用不同类型的连接或连接条件?)

【问题讨论】:

    标签: sql oracle plsql


    【解决方案1】:

    您在 DATE_STMP 上完成了完全外部联接记录。所以你会得到匹配和不匹配(即日期在另一个表中没有匹配)。您的结果表明您甚至没有匹配项,而只有不匹配项。但是,您似乎对有多少日期匹配完全不感兴趣。此外,我敢说您似乎甚至对年份匹配的频率都不感兴趣。您只想计算这两个表中每年的记录。这与匹配记录和连接无关。

    所以:首先获取计数。然后将结果加入,以便每年获得一条记录:

    select coalesce(t1.the_year,t2.the_year), t1.the_count, t2.the_count
    from
    (
      select extract (year from date_stmp) the_year, count(*) as the_count 
      from emp_1
      group by extract (year from date_stmp)
    ) t1
    full outer join
    (
      select extract (year from date_stmp) the_year, count(*) as the_count 
      from emp_2@link on
      group by extract (year from date_stmp)
    ) t2 on t2.the_year = t1.the_year;
    

    编辑:我看到您更改了请求的查询并按年加入。不过,如前所述,我认为您对计算匹配和不匹配不感兴趣,所以我的答案保持不变。

    【讨论】:

    • 与 pl/sql 代码相比,select 查询会更高效吗?
    • 是的,当然。使用 SQL,您可以直接访问数据,并且此选择很简单。对于 PL/SQL,它总是从 PL/SQL 引擎调用到 SQL 引擎。毫无疑问,这很快,但不如只停留在 SQL 中那么快。
    【解决方案2】:

    另一种方法是将union all 与聚合一起使用:

    SELECT y1, cnt1, y2, cnt2
    FROM ((SELECT EXTRACT(YEAR FROM Tab_1.DATE_STMP) as y1, COUNT(*) as cnt1, NULL as y2, NULL as cnt2
           FROM EMP_1 Tab_1
           GROUP BY EXTRACT(YEAR FROM Tab_1.DATE_STMP)
           EMP_2@LINK Tab_2  
          ) UNION ALL
          (SELECT NULL, NULL, EXTRACT(YEAR FROM Tab_2.DATE_STMP) as y2, COUNT(*) as cnt2
           FROM EMP_1 Tab_2
           GROUP BY EXTRACT(YEAR FROM Tab_2.DATE_STMP)
          )
         )  
    GROUP BY COALESCE(y1, y2)
    

    【讨论】:

      【解决方案3】:

      我认为最好将每个表分组在单独的select

      SELECT TAB_1.YEAR1, TAB_1.COUNT1, TAB_2.YEAR2, TAB_2.COUNT2
      
      FROM 
      (SELECT EXTRACT (YEAR FROM DATE_STMP) AS YEAR1, COUNT(DATE_STMP) AS COUNT1
      FROM EMP_1
      GROUP BY EXTRACT (YEAR FROM DATE_STMP)) AS TAB_1
      
      FULL OUTER JOIN
      
      (SELECT EXTRACT (YEAR FROM DATE_STMP) AS YEAR2, COUNT(DATE_STMP) AS COUNT2
      FROM EMP_2
      GROUP BY EXTRACT (YEAR FROM DATE_STMP)) AS TAB_2
      
      ON TAB_1.YEAR1=TAB_2.YEAR2;
      

      【讨论】:

      • 请从子查询中删除 TAB_1.TAB_2.。确实给出了预期的结果。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-16
      • 1970-01-01
      • 1970-01-01
      • 2015-04-01
      • 2023-03-10
      • 1970-01-01
      相关资源
      最近更新 更多