我正在尝试编写一个Oracle SQL查询来连接两个通过链接表链接的表(我的意思是一个包含2列的表,每个表都是主表的外键)。 min()函数用于将左外连接的结果限制为单行。
我的模特由"父母和#34;和"侄子"。父母可以有0个或更多的侄子。可以启用或禁用父母。每个侄子都有一个生日。我的查询的目标是:
为每个已启用的父级打印一行,列出父级最老的侄子(即带有分钟(生日)的侄子)。
我的问题在这里通过sqlfiddle来说明:http://sqlfiddle.com/#!4/9a3be0d/1
我可以为已启用的父母列出所有侄子的查询,但这还不够好 - 我只希望每个父母一行,其中只包含年龄侄子。将where子句形成外表似乎是我的绊脚石。
我的表格和示例数据:
create table parent (parent_id number primary key, parent_name varchar2(50), enabled int);
create table nephew (nephew_id number primary key, birthday date, nephew_name varchar2(50));
create table parent_nephew_link (parent_id number not null, nephew_id number not null);
parent table:
+----+-------------+---------+
| id | parent_name | enabled |
+----+-------------+---------+
| 1 | Donald | 1 |
+----+-------------+---------+
| 2 | Minnie | 0 |
+----+-------------+---------+
| 3 | Mickey | 1 |
+----+-------------+---------+
nephew table:
+-----------+------------+-------------+
| nephew_id | birthday | nephew_name |
+-----------+------------+-------------+
| 100 | 01/01/2017 | Huey |
+-----------+------------+-------------+
| 101 | 01/01/2016 | Dewey |
+-----------+------------+-------------+
| 102 | 01/01/2015 | Louie |
+-----------+------------+-------------+
| 103 | 01/01/2014 | Morty |
+-----------+------------+-------------+
| 104 | 01/01/2013 | Ferdie |
+-----------+------------+-------------+
parent_nephew_link table:
+-----------+-----------+
| parent_id | nephew_id |
+-----------+-----------+
| 1 | 100 |
+-----------+-----------+
| 1 | 101 |
+-----------+-----------+
| 1 | 102 |
+-----------+-----------+
| 3 | 103 |
+-----------+-----------+
| 3 | 104 |
+-----------+-----------+
我的(不正确)查询:
-- This query is not right, it returns a row for each nephew
select parent_name, nephew_name
from parent p
left outer join parent_nephew_link pnl
on p.parent_id = pnl.parent_id
left outer join nephew n
on n.nephew_id = pnl.nephew_id
where enabled = 1
-- I wish I could add this clause to restrict the result to the oldest
-- nephew but p.parent_id is not available in sub-selects.
-- You get an ORA-00904 error if you try this:
-- and n.birthday = (select min(birthday) from nephew nested where nested.parent_id = p.parent_id)
我想要的输出是:
+-------------+-------------+
| parent_name | nephew_name |
+-------------+-------------+
| Donald | Louie |
+-------------+-------------+
| Mickey | Ferdie |
+-------------+-------------+
感谢您的任何建议! 约翰
我尝试过使用markaaronky的建议,但这个sql也存在缺陷。
-- This query is not right either, it returns the correct data but only for one parent
select * from (
select parent_name, n.nephew_name, n.birthday
from parent p
left outer join parent_nephew_link pnl
on p.parent_id = pnl.parent_id
left outer join nephew n
on n.nephew_id = pnl.nephew_id
where enabled = 1
order by parent_name, n.birthday asc
) where rownum <= 1
答案 0 :(得分:0)
为什么不: (1)在SELECT语句中包含来自nephews表的n.birthday (2)在您的查询中添加ORDER BY n.birthday ASC (3)还修改你的选择,使它只占用顶行?
我试着在sqlfiddle中为你写这个,但它似乎不喜欢表别名(例如,当我写n.birthday时它会抛出错误),但我确信这在Oracle中是合法的,即使我是一个SQL Server人。
另外,如果我没记错,Oracle没有像SQL Server那样的SELECT TOP ......你必须做一些类似“WHERE ROWNUM = 1”的事情吗?同样的概念......你只是订购你的结果,所以最老的侄子是第一排,而你只是第一排。
也许一个不受欢迎的副作用是你将获得生日以及结果中的名字。如果这是不可接受的,我道歉。看起来你的问题暂时没有答案,这个解决方案至少应该给你一个开始。
最后,由于您的生日列上没有NOT NULL约束并且正在执行左外连接,因此可以通过添加AND n.birthday IS NOT NOT来使查询更安全
答案 1 :(得分:0)
使用:
select parent_name, nephew_name
from parent p
left outer join
(
SELECT pnl.parent_id, n.nephew_name
FROM parent_nephew_link pnl
join nephew n
on n.nephew_id = pnl.nephew_id
AND n.BIRTHDAY = (
SELECT min( BIRTHDAY )
FROM nephew n1
JOIN parent_nephew_link pnl1
ON pnl1.NEPHEW_ID = n1.NEPHEW_ID
WHERE pnl1.PARENT_ID = pnl.PARENT_ID
)
) ppp
on p.parent_id = ppp.parent_id
where p.enabled = 1
演示:http://sqlfiddle.com/#!4/98758/23
| PARENT_NAME | NEPHEW_NAME |
|-------------|-------------|
| Mickey | Louie |
| Donald | Ferdie |