如何将多个表与另一个表联接在一起?

时间:2020-03-04 23:26:24

标签: sql join

我不确定问题的标题!,但是我有这个问题

 table1 
   id    |  from  |  to
   1         A       B
   2         C       A
   3         B       A

 table2 
   id    |  table1_id
   1         1      
   2         1       
   3         1           
   4         3       
   5         3
   6         2      
   7         2       
   8         2

我需要从table1获取数据,并将具有id(2,3)的行视为一行,并与table2联接 获取它们之间的最后一个ID 5
结果

   id    |  from     |   to     |   table2_id
   3         B       |    A     |    5
   2         C       |    A     |    8

2 个答案:

答案 0 :(得分:0)

您没有提到数据库,我已经在SQL Server中编写了SQL

WITH TAB_FLAT AS 
(
SELECT TAB_1.table1_id , COALESCE ( TAB_2.table2_id , TAB_1.table2_id ) max_id , TAB_1.table2_id FROM 
( select table1_id , max(id) table2_id from table2 group by table1_id ) TAB_1 
LEFT JOIN  
( select table1_id , max(id) table2_id from table2 group by table1_id ) TAB_2
ON TAB_1.table2_id = TAB_2.table1_id
)
select TAB_FLAT.table1_id AS ID, COALESCE(C.frm ,COALESCE(B.frm,A.frm) ) AS 'FROM' , 
COALESCE(C.to2 ,COALESCE(B.to2,A.to2) ) AS 'TO' , 
TAB_FLAT.max_id AS table2_id
FROM TAB_FLAT 
LEFT JOIN table1 A ON A.id = TAB_FLAT.table1_id
LEFT JOIN table1 B ON B.id = TAB_FLAT.table2_id
LEFT JOIN table1 C ON C.id = TAB_FLAT.max_id
WHERE  TAB_FLAT.table1_id IN (1,2) 

演示-> https://rextester.com/DCHUN74655

说明:

SELECT TAB_1.table1_id , COALESCE ( TAB_2.table2_id , TAB_1.table2_id ) max_id , TAB_1.table2_id FROM 
( select table1_id , max(id) table2_id from table2 group by table1_id ) TAB_1 
LEFT JOIN  
( select table1_id , max(id) table2_id from table2 group by table1_id ) TAB_2
ON TAB_1.table2_id = TAB_2.table1_id

我们正在执行自左联接,以获取每个表1 ID的最大表2 ID AND相应的中间级别。

select TAB_FLAT.table1_id AS ID, COALESCE(C.frm ,COALESCE(B.frm,A.frm) ) AS 'FROM' , 
COALESCE(C.to2 ,COALESCE(B.to2,A.to2) ) AS 'TO' , 
TAB_FLAT.max_id AS table2_id
FROM TAB_FLAT 
LEFT JOIN table1 A ON A.id = TAB_FLAT.table1_id
LEFT JOIN table1 B ON B.id = TAB_FLAT.table2_id
LEFT JOIN table1 C ON C.id = TAB_FLAT.max_id

我们正在基于表1 id,中间id和最大id加入表1

WHERE  TAB_FLAT.table1_id IN (1,2) 

过滤出ID为1或2的记录

答案 1 :(得分:-1)

首先,编写查询以获取表2中每一行的最大ID。

select t1.*, max(t2.id) as table2_id
from table2 t2
join table1 t1 on t2.table1_id = t1.id
group by t1.id

然后将其用作两个查询的CTE。一种用于获取除 1和3之外的所有行。另一种用于获取1或3,以较大的table2_id为准。 union一起。

with max_table2 as (
  select t1.*, max(t2.id) as table2_id
  from table2 t2
  join table1 t1 on t2.table1_id = t1.id
  group by t1.id
)
select *
from max_table2
where id not in (1,3)
union
(
  select *
  from max_table2
  where id in (1,3)
  order by table2_id desc
  limit 1
)

如果合并的1/3行必须的ID为1,尽管3的table2_id较大,则可以通过在选择查询中对ID进行硬编码来实现。

with max_table2 as (
  select t1.*, max(t2.id) as table2_id
  from table2 t2
  join table1 t1 on t2.table1_id = t1.id
  group by t1.id
)
select *
from max_table2
where id not in (1,3)
union
(
  select 1 as id, "from", "to", table2_id
  from max_table2
  where id in (1,3)
  order by table2_id desc
  limit 1
)

Try it.


我怀疑不是硬编码第1行和第3行,您实际上是将它们视为等效的,因为它们具有相同的路径,只是反向了。我们可以使该查询更通用。

首先,对from / to进行规范化,以使它们的顺序相同。在进行此操作时,还要获取其最大table2 id。

select
  t1.id,
  case when "from" < "to" then "from" else "to" end as "from",
  case when "from" < "to" then "to" else "from" end as "to",
  max(t2.id) as max_table2_id
from table2 t2
join table1 t1 on t2.table1_id = t1.id
group by t1.id


id  from    to  max_table2_id
2   A       C   8
3   A       B   5
1   A       B   3

然后使用相同的从/到路径对路径进行排名。

with normalized_max_table2 as (
select
  t1.id,
  case when "from" < "to" then "from" else "to" end as "from",
  case when "from" < "to" then "to" else "from" end as "to",
  max(t2.id) as table2_id
from table2 t2
join table1 t1 on t2.table1_id = t1.id
group by t1.id
)
select *,
  rank() over (partition by "from", "to" order by table2_id desc) as "rank"
from normalized_max_table2


id  from    to  table2_id   rank
3   A       B   5           1
1   A       B   3           2
2   A       C   8           1

最后,仅选择第一名。

with normalized_max_table2 as (
select
  t1.id,
  case when "from" < "to" then "from" else "to" end as "from",
  case when "from" < "to" then "to" else "from" end as "to",
  max(t2.id) as table2_id
from table2 t2
join table1 t1 on t2.table1_id = t1.id
group by t1.id
),
ranked_max_table2 as (
  select *,
    rank() over (partition by "from", "to" order by table2_id desc) as "rank"
  from normalized_max_table2
)
select id, "from", "to", table2_id
from ranked_max_table2
where "rank" = 1


id  from    to  table2_id
3   A       B   5
2   A       C   8

这是一种长期的做法。可能会有更紧凑的方法。

Try it