三个表连接未提供所需的输出

时间:2016-06-20 03:36:20

标签: sql-server tsql join

我有三张桌子:

1:Station_Details(主数据表)
2:RF_Details
3:WL_Details

如下图所示。 我需要一个从所有三个表中的数据到输出表 来自Station_details的主数据和来自RF和WL表的其他数据。 如果RF_Details和WL_Details表具有相同的站ID且具有相同的DateTime,则在输出表中,两行详细信息将显示在一行中。 如果DateTime不同,那么它将出现在不同的行中。

我尝试过这个sql查询,但是我没有像OUTPUT Table那样获得相同的输出。

  select rf.StationID, st.stationname, st.state,rf.rf,rf.cum-rf,wl.wl,DataTime 
     from  [RF_Details] rf
     join [WL_Details] wl
    join Station_Details st
    on rf.StationID = wl.StationId and
       rf.DataRecieved=wl.DataRecieved and
       st.stationid =rf.stationid and
       st.stationid = wl.stationid;

但它没有给出正确的行数和输出。 请帮助我。

enter image description here

3 个答案:

答案 0 :(得分:2)

您应始终将连接条件与连接本身一起放置。此外,添加INNER是我遵循的做法,以确保不会返回额外的记录。

SELECT rf.StationID, st.stationname, st.state, wl.DataRecieved, wl.waterlevel1,
    rf.dailyrainfall, rf.cumrainfall
FROM  [RF_Details] rf
INNER JOIN [WL_Details] wl
ON rf.StationID = wl.StationId AND
   rf.DataRecieved=wl.DataRecieved
INNER JOIN Station_Details st
ON st.stationid =rf.stationid AND
   st.stationid = wl.stationid;

答案 1 :(得分:1)

declare @station_details table(id int, station_id varchar(10),station_name varchar(10),state varchar(10))
declare @rf_details table (id int, station_id varchar(10),rf int, cum_rf int, dt dateTIME)
declare @wl_details table (id int, station_id varchar(10),wl int,dt datetime)

insert into @station_details values
(1,'DEL-NDL','NDL','DEL'),
(2,'UP-LKO','LKO','UP'),
(3,'MP-BHP','BHP','MP'),
(4,'MHR-MUM','MUM','MHR')

INSERT INTO @RF_DETAILS VALUES
(1,'DEL-NDL',42,435,'2016-06-13 05:15:00'),
(2,'UP-LKO',0,501,'2016-06-13 05:15:00'),
(3,'MP-BHP',20,350,'2016-06-13 05:15:00'),
(4,'MHR-MUM',30,200,'2016-06-13 05:15:00'),
(5,'MHR-MUM',15,100,'2016-06-14 05:15:00'),
(6,'UP-LKO',50,350,'2016-06-13 05:15:00')

INSERT INTO @WL_DETAILS VALUES
(1,'DEL-NDL',25,'2016-06-13 05:15:00'),
(2,'UP-LKO',35,'2016-06-13 05:30:00'),
(3,'MP-BHP',46,'2016-06-13 05:45:00'),
(4,'MHR-MUM',20,'2016-06-13 05:15:00'),
(5,'MHR-MUM',15,'2016-06-14 05:15:00'),
(6,'UP-LKO',60,'2016-06-13 05:15:00')

;with cte as
(
SELECT  case 
        when rf.dt = wl.dt then 'Y' 
        else 'N'
        end as matched,
        rf.id as id,rf.station_id as stationid,rf.rf as rf , rf.cum_rf as cumrf , rf.dt as rfdt, 
        wl.id as wlid, wl.station_id ,wl.wl ,wl.dt as wldte, 
        rf.station_id as station,rf.dt as rfdte
FROM    @RF_DETAILS RF
JOIN      @WL_DETAILS WL ON rf.id = wl.id and RF.STATION_ID = WL.STATION_ID
)
select  row_number() over (order by s.id) newid,
        s.id,s.station_id,sd.station_name,sd.state,s.rf,s.cumrf,s.wl,
        case
        when s.srce = 'L' then s.rfdte 
        else s.wldte
        end as 'Date'
from
(
select 'L' as srce,cte.id,cte.station_id,cte.rf,cte.cumrf, cte.wl as wl, cte.rfdte,cte.wldte from cte where cte.matched = 'Y'
union
select 'L' as srce,cte.id,cte.station_id,cte.rf,cte.cumrf, null as wl, cte.rfdte,cte.wldte from cte where cte.matched = 'N'
union all
select 'R' as srce,cte.id * 10,cte.station_id,null,null, cte.wl as wl, cte.rfdte,cte.wldte from cte where cte.matched = 'N'
) s
join    @station_details sd on sd.station_id = s.station_id
order   by s.id

答案 2 :(得分:0)

您应该重新设计数据库:现在您在RF_Details和WL_Details - DateTime中有一个辅助密钥。它们在它们之间起着外键的作用。哪个不好,每次你需要加入这些表或收集相应的数据时都会让你感到困惑。

应该有另一个像Station_Records这样的表,它会为该站的每条记录存储一行:(id, station_id, record_date_time)RFWL行(如果有的话)应引用此表格,而不是Station_Detailsstation_id相互引用,而datetime引用{。}}。

使用当前结构,您需要完全加入RFWL以获得两者:按日期时间匹配 - 在同一行中,不匹配 - 在单独的行中。

select sd.station_name, Station_Records.*
from Station_Details sd
inner join
(
  select
    IsNull(rf.station_id, wl.station_id) station_id,
    IsNull(rf.DataRecieved, wl.DataRecieved) DataRecieved,
    rf.rf, rf.cum-rf, wl.wl
  from [RF_Details] rf
  full join [WL_Details] wl
  on wl.station_id = rf.station_id
    and wl.DataRecieved = rf.DataRecieved
) Station_Records
on Station_Records.station_ud = sd.station_id

具体实现可能包含OUTER APPLY,甚至没有任何子查询 - 目前并不重要。

修改表格结构,您将始终知道所有匹配的记录:

select
  sd.station_id, sd.station_name,
  sr.DataRecieved
  rf.rf, rf.cum-rf,
  wl.wl
from Station_Details sd
inner join Station_Records sr
on sr.station_id = sd.station_id
left join RF_Details rf
on rf.record_id = sr.record_id
left join WL_Details wl
on wl.record_id = sr.record_id