如何根据另一列的值查找列的值?

时间:2017-04-12 08:25:45

标签: sql database postgresql

我有一个简单的地铁线路系统,模仿如下:

  • 一条线有多个站点。
  • 每个电台都有时间表。
  • 时间表包含一些时间信息和表示时间信息所在行方向的方向。

我的问题是,如果有时间表,我如何找到属于该方向线的终端站?

我的表格结构如下:

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_starttrue,则表示方向指向的网站的订单为1falsemax(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_startfalse,它指向行尾,应为Station C)?

我使用postgresql并且我的初始尝试依赖多次连接到数据库,在这种情况下,我首先根据给定的id选择计划,保存其to_startstation_id,然后选择相应的电台使用已保存的station_id,保存其line_id,并根据to_start的值,选择line_id的电台和order 1 1}},或首先找到max(order),然后选择line_id和最大订单的电台。

感觉非常麻烦,不要让postgresql尽可能地进行最佳优化。

有没有办法用一个sql做到这一点?

3 个答案:

答案 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是保留关键字,因此将其用作列名
  • 是不明智的
  • 你的架构对我来说有点奇怪,f.ex。你需要复制电台,如果有多条线路正在穿越它

http://rextester.com/OITNB38639

答案 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