2017-02-20 15 views
1

我正在努力處理涉及自反關係和Oracle語法的數據庫情況。我可以拿出我現在的問題最好的比喻是:Oracle Syntax&選擇自反關係中的最大和最小行數

關係表:

------------------------------------------------------------ 
| 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 | 
------------------------------------------------------------ 

查詢:

我試圖選擇是最古老和最新的兩行(WRT「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; 

幫助是非常感謝!謝謝!

+1

您使用的是MySQL還是Oracle? (不要標記不涉及的產品。) – jarlh

+0

我這樣做的目的是希望可能有一個直接的SQL解決方案,它可以與 – QNeville

+0

無關。如果您有另一對具有相同最小「STARTED」值的人,您的預期輸出是什麼?只返回具有最小值的第一行(忽略第二對)或從兩個對返回一行(並且以最小值輸出兩行)? – MT0

回答

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; 

最後一行基本上照顧它。由於一個人不會與自己建立關係,這就迫使反身關係只能走一條路。

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 
1

這將只返回一個最大和一個最小的行(類似於你LIMIT 1UNION查詢):

甲骨文設置

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 
+0

謝謝!這有效,但我發現了一個更簡單的解決方案來處理反身關係,並削減了一半的桌子。 – QNeville