Oracle语法&选择自反关系中的最大行数和最小行数

时间:2017-02-20 07:33:41

标签: mysql sql oracle

我正在努力解决涉及自反关系和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;

非常感谢帮助!谢谢!

3 个答案:

答案 0 :(得分:1)

这将只返回一个最大行和一个最小行(类似于UNIONLIMIT 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; 

最后一行基本上都是照顾它。由于一个人不会与自己建立关系,这会迫使反身关系只走一条路。