我正在努力解决涉及自反关系和Oracle语法的数据库问题。我能解决当前问题的最佳比喻是:
关系表:
------------------------------------------------------------
| PERSON1 | PERSON2 | STARTED | ENDED |
------------------------------------------------------------
| Some Guy | Some Lady | 1998 | 2000 |
| Some Lady | Some Guy | 1998 | 2000 |
| .... | .... | .... | .... |
| .... | .... | .... | .... |
| .... | .... | .... | .... |
| .... | .... | .... | .... |
| Another Guy | Another Lady | 1992 | 2005 |
| Another Lady | Another Guy | 1992 | 2005 |
------------------------------------------------------------
查询:
我想要选择的是最旧和最新的行(W.R.T。" STARTED")。如果这不是一种反身关系,那么很容易回归:
------------------------------------------------------------
| PERSON1 | PERSON2 | STARTED | ENDED |
------------------------------------------------------------
| Some Guy | Some Lady | 1998 | 2000 |
| Another Guy | Another Lady | 1992 | 2005 |
------------------------------------------------------------
由此:
SELECT PERSON1, PERSON2, STARTED, ENDED
FROM RELATIONSHIPS
WHERE (STARTED) IN
(
SELECT MAX(STARTED) AS START_YEAR FROM RELATIONSHIPS
UNION
SELECT MIN(STARTED) AS START_YEAR FROM RELATIONSHIPS
);
返回:
------------------------------------------------------------
| PERSON1 | PERSON2 | STARTED | ENDED |
------------------------------------------------------------
| Some Guy | Some Lady | 1998 | 2000 |
| Another Guy | Another Lady | 1992 | 2005 |
| Some Lady | Some Guy | 1998 | 2000 |
| Another Lady | Another Guy | 1992 | 2005 |
------------------------------------------------------------
......当我真的只需要前两行(订单无法保证)
如果我没有使用Oracle,我知道我可以使用可接受的东西(除非有人也知道更好的方法):
SELECT PERSON1, PERSON2, STARTED, ENDED
FROM RELATIONSHIPS
ORDER BY STARTED DESC
LIMIT 1
UNION
SELECT PERSON1, PERSON2, STARTED, ENDED
FROM RELATIONSHIPS
ORDER BY STARTED ASC
LIMIT 1;
非常感谢帮助!谢谢!
答案 0 :(得分:1)
这将只返回一个最大行和一个最小行(类似于UNION
个LIMIT 1
个查询):
Oracle安装程序:
CREATE TABLE relationships (PERSON1, PERSON2, STARTED, ENDED) as
SELECT 'Some Guy' ,'Some Lady' ,1998, 2000 FROM DUAL UNION ALL
SELECT 'Some Lady' ,'Some Guy' ,1998, 2000 FROM DUAL UNION ALL
SELECT 'Another Guy' ,'Another Lady',1992, 2005 FROM DUAL UNION ALL
SELECT 'Another Lady' ,'Another Guy' ,1992, 2005 FROM DUAL;
<强>查询强>:
SELECT person1, person2, started, ended
FROM (
SELECT r.*,
ROW_NUMBER() OVER ( ORDER BY started ASC ) AS rn_asc,
ROW_NUMBER() OVER ( ORDER BY started DESC ) AS rn_desc
FROM relationships r
)
WHERE rn_asc = 1 OR rn_desc = 1;
<强>输出强>:
PERSON1 PERSON2 STARTED ENDED
------------ ----------- ------- -----
Some Guy Some Lady 1998 2000
Another Lady Another Guy 1998 2005
答案 1 :(得分:0)
我制作下一个解决方案。我只在oracle数据库上测试它,但它也应该与mysql一起使用。
with RELATIONSHIPS(PERSON1,PERSON2,STARTED,ENDED) as (
select 'Some Guy','Some Lady', 1998, 2000 from dual union all
select 'Another Guy' ,'Another Lady',1992,2005 from dual union all
select 'Some Lady','Some Guy', 1998, 2000 from dual union all
select 'Another Lady','Another Guy' ,1992,2005 from dual)
select distinct
least(PERSON1,PERSON2) as PERSON1 ,
greatest(PERSON1,PERSON2) as PERSON2,
STARTED,
ENDED
from RELATIONSHIPS r
join (
SELECT MAX(STARTED) AS START_YEAR FROM RELATIONSHIPS
UNION
SELECT MIN(STARTED) AS START_YEAR FROM RELATIONSHIPS
) st on r.STARTED = START_YEAR
答案 2 :(得分:0)
感谢您的帮助。这很简单,我从未意识到这一点。
SELECT PERSON1, PERSON2, STARTED, ENDED
FROM RELATIONSHIPS
WHERE (STARTED) IN
(
SELECT MAX(STARTED) FROM RELATIONSHIPS
UNION
SELECT MIN(STARTED) FROM RELATIONSHIPS
)
AND PERSON1 < PERSON2;
最后一行基本上都是照顾它。由于一个人不会与自己建立关系,这会迫使反身关系只走一条路。