简体   繁体   中英

Join and compare 2 queries of 2 tables

This is probably a quite trivial question for many here but I am not used to write sub queries and joins, so I hope someone want to help.

I have two tables: new_road and old_roads.

These two queries sum up the length of the roads belonging to a specific road number.

SELECT new_road.nummer, SUM(new_road.length) FROM road_table.road GROUP BY new_road.nummer

SELECT old_road.nummer, SUM(ST_length(old_road.geom)) FROM old_road_table.old_road GROUP BY old_road.nummer

I wish to have a result table where these two queries are joined so I can compare the new and old summed length for each road number.

Like

old.nummer old.length new.nummer new.lenght
2345       10.3       2345       10.5      
2346       578.2      2346       600
2347       54.2       NULL       NULL
NULL       NULL       2546       32.2

I think some version of an outer join is needed because there will be a road numbers in the old_road table that does not exist in the new.road table and i would like to see them too.

Appreciate any advice

Edit:

After advice from below did I came up with this:

SELECT * FROM
(SELECT new_road.nummer, SUM(new_road.length) FROM road_table.road GROUP BY new_road.nummer) new_table
FULL OUTER JOIN
(SELECT old_road.nummer, SUM(ST_length(old_road.geom)) FROM old_road_table.old_road GROUP BY old_road.nummer) old_table
ON new_road.nummer = old_road.nummer

But each time I run it I get missing FROM-clause entry. When I run each sub query individually they work. I have crosschecked with the documentation and it look OK to me, but clearly I am missing something here.

Consider using a FULL OUTER JOIN

This is not the exact output you requested but you don't need to display the nummer twice.

SELECT
    COALESCE(new_road.nummer,old_road.nummer)nummer,
    new_road.length,
    old_road.length
FROM (
    SELECT new_road.nummer
        ,SUM(new_road.length) length
    FROM road_table.road
    GROUP BY new_road.nummer
) new_road 
FULL OUTER JOIN (
    SELECT old_road.nummer
        ,SUM(ST_length(old_road.geom))length
    FROM old_road_table.old_road
    GROUP BY old_road.nummer
) old_road ON
    old_road.nummer = new_road.nummer

Following query should solve the purpose. I didn't run it but the basic idea is result of a query on a table is another table on which you can query again.

Select * FROM (SELECT new_road.nummer, SUM(new_road.length) FROM road_table.road GROUP BY new_road.nummer) table1 JOIN (SELECT old_road.nummer, SUM(ST_length(old_road.geom)) FROM old_road_table.old_road GROUP BY old_road.nummer) table2 ON table1.new_road.nummer = table2.old_road.nummer

The tricky bit here is that you want to make sure you include all of the keys from both lists. My favorite way to do this kind of thing is:

select * from (
  SELECT distinct new_road.nummer as nummer from road_table.road
  union
  SELECT distinct old_road.nummer as nummer FROM old_road_table.old_road
) allkeys
left join
(
  SELECT new_road.nummer as nummer, SUM(new_road.length) as nlen
  FROM road_table.road GROUP BY new_road.nummer
) n 
  on allkeys.nummer = n.nummer
left join 
(
  SELECT old_road.nummer as nummer, SUM(ST_length(old_road.geom)) as olen
  FROM old_road_table.old_road GROUP BY old_road.nummer
) o
  on allkeys.nummer = o.nummer

The first subquery builds a list of all keys, then you join to both of your queries from there. There's nothing wrong with an outer join, but I find this easier to manage if you have to include 3 or more tables. If you had to include another table it would just be one more union in allkeys and one more left join to that table.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM