我有一个简单的地铁线路系统,模仿如下:
我的问题是,如果有时间表,我如何找到属于该方向线的终端站?
我的表格结构如下:
CREATE TABLE schedule (
id serial PRIMARY KEY,
to_start boolean,
start_time time,
end_time time,
station_id REFERENCES station
);
CREATE TABLE station (
id serial PRIMARY KEY,
name varchar,
order integer,
line_id integer REFERENCES line
);
CREATE TABLE line (
id serial PRIMARY KEY,
name varchar
);
如果schedule.to_start
为true
,则表示方向指向的网站的订单为1
,false
为max(order)
。
以下是一些示例数据:
日程表
id | to_start | start_time | end_time | station_id
----+----------+------------+----------+------------
1 | f | 06:02:00 | 22:02:00 | 2
2 | t | 06:35:00 | 23:07:00 | 2
站台
id | name | order | line_id
----+--------------+--------+---------
1 | Station A | 1 | 1
2 | Station B | 2 | 1
3 | Station C | 3 | 1
4 | Station D | 1 | 2
行表
id | name
----+--------
1 | Line 1
2 | Line 2
因此,如果给出schedule.id
之类的1
值,我如何找到应该为station.name
的相应Station C
(因为该时间表是带有2
的工作站1}},属于ID为1
的行,而to_start
为false
,它指向行尾,应为Station C
)?
我使用postgresql并且我的初始尝试依赖多次连接到数据库,在这种情况下,我首先根据给定的id选择计划,保存其to_start
和station_id
,然后选择相应的电台使用已保存的station_id
,保存其line_id
,并根据to_start
的值,选择line_id
的电台和order
1
1}},或首先找到max(order)
,然后选择line_id
和最大订单的电台。
感觉非常麻烦,不要让postgresql尽可能地进行最佳优化。
有没有办法用一个sql做到这一点?
答案 0 :(得分:1)
您可以使用连接执行此操作。您可以在一个查询中执行多个连接。
SELECT * FROM schedule JOIN station on station.id = schedule.station_id JOIN line line.id = schedule.line_id WHERE sechdule.id = '1'
有关联接的更多信息: https://www.w3schools.com/sql/sql_join.asp
答案 1 :(得分:1)
这样做:
select ds.*
from schedule s
join station qs on qs.id = s.station_id
join station ds using (line_id)
where s.id = 1
order by ds."order" * case when s.to_start then 1 else -1 end
limit 1
注意:
order
是保留关键字,因此将其用作列名答案 2 :(得分:0)
一些CTE,一个新的row_number()和一些可爱的自联接
with FirstLast as
(
select a1.*,
row_number() over(partition by line_id order by a1.order desc) as order2
from Station a1
)
, Stage2 as
(
select a1.id, a1.name, a2.name as FirstStation, a3.name as LastStation
from FirstLast a1
inner join FirstLast a2
on a1.line_id = a2.line_id
and a2.order = 1
inner join FirstLast a3
on a1.line_id = a3.line_id
and a3.order2 = 1
)
select x.id,
x.name,
case
when z.to_start = 't' then x.FirstStation
else x.LastStation
end as TheStation
from schedule z
inner join Stage2 x
on z.station_id = x.id