假设我们有这些(从更复杂的一个简化)示例表:
== st == == pr === == rn === <– tables
sta pg pg rou sta rou <– fields
======== ========= =========
H1 aa aa aaA H1 aaA
H2 aa aa aaB H2 aaB
H3 aa H3 aaB
H4 aa aa aaC H4 aaC
H5 aa H5 aaC
H6 aa H6 aaC
H7 aa
H8 bb bb NULL
我想用左内连接执行此(也简化)查询:
SELECT st.*, pr.*, rn.*
FROM st
INNER JOIN ( pr
LEFT JOIN rn ON pr.rou = rn.rou
AND rn.sta = st.sta -- ERROR here
) ON pr.pg = st.pg
-- filter out bad rows
WHERE ( rn.id ) -- a: not null
OR ( pr.rou ='aaC' AND rn.id IS NULL) -- b: no joinable rn found: choose
-- by a predefined pr.rou value
OR ( pr.rou IS NULL ) -- c: no need to join
得到这个结果:
== st == == pr === == rn ===
sta pg pg rou sta rou
======== ========= =========
H1 aa aa aaA H1 aaA
H2 aa aa aaB H2 aaB
H3 aa aa aaB H3 aaB
H4 aa aa aaC H4 aaC
H5 aa aa aaC H5 aaC
H6 aa aa aaC H6 aaC
H7 aa aa aaA NULL NULL \ H7 has no rn, so choose
H7 aa aa aaB NULL NULL } 1 row of these at the
H7 aa aa aaC NULL NULL / WHERE / b condition
H8 bb bb NULL NULL NULL
但是MySQL抛出了这个错误:#1054 - Unknown column 'st.sta' in 'on clause'
。
我尝试解决这个问题没有成功,直到有人发布(并删除)了两次加入rn
列的好主意。感谢他/她,我能够创建一个有效的解决方案:
SELECT st.*, pr.*, rn.*, rn2.*
FROM st
INNER JOIN pr ON st.pg = pr.pg
LEFT JOIN rn ON st.sta = rn.sta
LEFT JOIN rn AS rn2 ON pr.rou = rn2.rou -- the two rn's join order is important
AND rn.id = rn2.id -- if first exists, second must match or null, first null => second null
WHERE ( rn.id = rn2.id ) -- a: both not null
OR ( pr.rou ='aaC' AND rn.id IS NULL) -- b: no joinable rn found: choose by predefined pr.rou value
OR ( pr.rou IS NULL ) -- c: no need to join
虽然这个查询有效,但它需要以正确的顺序重复连接,非常脆弱和丑陋。
你能提供一个更清洁的解决方案,它只加入rn
表一次吗?
以下是sql中用于copypasting的示例数据库,如果你想玩它:
DROP TABLE IF EXISTS st;
CREATE TABLE IF NOT EXISTS st (
id int AUTO_INCREMENT,
sta varchar(9),
pg varchar(9),
PRIMARY KEY ( id )
) AUTO_INCREMENT=1;
DROP TABLE IF EXISTS pr;
CREATE TABLE IF NOT EXISTS pr (
id int AUTO_INCREMENT,
pg varchar(9),
rou varchar(9),
PRIMARY KEY ( id )
) AUTO_INCREMENT=1;
DROP TABLE IF EXISTS rn;
CREATE TABLE IF NOT EXISTS rn (
id int AUTO_INCREMENT,
sta varchar(9),
rou varchar(9),
PRIMARY KEY ( id )
) AUTO_INCREMENT=1;
INSERT INTO st
(sta , pg ) VALUES
('H1','aa'),
('H2','aa'),
('H3','aa'),
('H4','aa'),
('H5','aa'),
('H6','aa'),
('H7','aa'),
('H8','bb');
INSERT INTO pr
( pg , rou ) VALUES
('aa','aaA'),
('aa','aaB'),
('aa','aaC'),
('bb', NULL);
INSERT INTO rn
(sta , rou ) VALUES
('H1','aaA'),
('H2','aaB'),
('H3','aaB'),
('H4','aaC'),
('H5','aaC'),
('H6','aaC');
答案 0 :(得分:11)
我想我终于明白了:
SELECT st.*, pr.*, rn.*
FROM st
LEFT JOIN rn ON st.sta = rn.sta
LEFT JOIN pr ON st.pg = pr.pg
AND (rn.rou = pr.rou OR rn.rou IS NULL)
答案 1 :(得分:2)
select st.*, pr.*, rn.*
from st
left join pr on pr.pg = st.pg
left join rn on rn.sta = st.sta
答案 2 :(得分:1)
我快速测试了它,它似乎工作。我重命名了这些列,以显示它们应该代表的内容以符合您的预期结果。
SELECT
st.sta,
st.pg,
MIN( COALESCE( prByRN.pg, pr.pg )) prpg,
MIN( COALESCE( prByRN.rou, pr.rou )) prrou,
MIN( rn.sta ) rnsta,
MIN( rn.rou ) rnrou
from
st
left join rn
ON st.sta = rn.sta
LEFT JOIN pr prByrn
ON rn.rou = prByrn.rou
LEFT JOIN pr
ON st.pg = pr.pg
GROUP BY
st.sta,
st.pg
答案 3 :(得分:1)
此查询100%正确...
检查.....
Select st.sta,st.pg,pr.pg,pr.rou,rn.sta,rn.rou from st
Left join pr
On pr.pg=st.pg
Left join rn
On rn.sta=st.sta
您的结果是给出了这些查询...
如果有任何疑问,请尽快回复。
答案 4 :(得分:0)
SELECT st.*, pr.*, rn.*
FROM
st
LEFT JOIN
( pr --- the parenthesis are
LEFT JOIN
rn
ON pr.rou = rn.rou
) --- there for clarity
ON rn.sta = st.sta
AND pr.pg = st.pg