2016-03-03 60 views
1

我想解決這個問題,但是我找不到正確的解決方案。在XML表中練習XMLTABLE e XML

從表中獲取matchRound關於球隊的信息將在第三輪中發揮作用。在第三輪比賽中將打出第一輪對陣第二輪最佳陣容的最佳陣容。 訪問第三輪的一般規則是:

  1. 在贏得比賽
  2. 的最高數量在同等情況下,獲勝的是打進最後一球
  3. 如果相等的球隊,勝主隊

這是表:

CREATE TABLE matchRound (
round_num INTEGER, 
play_date DATE, 
home_team CHAR(2), 
visiting_team CHAR(2), 
goals XMLTYPE, 
PRIMARY KEY(play_date, home_team) 
); 


INSERT INTO matchRound VALUES (1, TO_DATE('1/1/2012', 'DD/MM/YYYY'), 'MI', 'IN', xmltype.createxml('<?xml version="1.0"?><goals><player team="MI" minute="62">De Rossi</player><player team="MI" minute="25">Pirlo</player></goals>')); 
INSERT INTO matchRound VALUES (1, TO_DATE('2/1/2012', 'DD/MM/YYYY'), 'MI', 'GE', xmltype.createxml('<?xml version="1.0"?><goals><player team="MI" minute="30">De Rossi</player><player team="GE" minute="25">Cannavaro</player></goals>')); 
INSERT INTO matchRound VALUES (1, TO_DATE('3/1/2012', 'DD/MM/YYYY'), 'IN', 'GE', xmltype.createxml('<?xml version="1.0"?><goals></goals>')); 
INSERT INTO matchRound VALUES (2, TO_DATE('4/1/2012', 'DD/MM/YYYY'), 'TO', 'JU', xmltype.createxml('<?xml version="1.0"?><goals><player team="JU" minute="40">Gattuso</player><player team="JU" minute="90">Rossi</player></goals>')); 
INSERT INTO matchRound VALUES (2, TO_DATE('5/1/2012', 'DD/MM/YYYY'), 'TO', 'SM', xmltype.createxml('<?xml version="1.0"?><goals><player team="TO" minute="20">Gialli</player><player team="TO" minute="30">Neri</player><player team="TO" minute="50">Verdi</player></goals>')); 
INSERT INTO matchRound VALUES (2, TO_DATE('6/1/2012', 'DD/MM/YYYY'), 'JU', 'SM', xmltype.createxml('<?xml version="1.0"?><goals><player team="JU" minute="20">Gattuso</player><player team="JU" minute="40">Rossi</player></goals>')); 

這是m的一部分y解決方案:

SELECT T1.round_num, T1.win, count(T1.win) as "GOALS" 
FROM (
    SELECT PG.round_num, PG.home_team AS "home", V.win 
    FROM matchRound PG, 
    XMLTABLE('let $x := //player[@team=$s1] 
     let $y := //player[@team=$s2] 
     let $z := //player 
     return if(count($x)=count($y)) then <win>{data($z[last()]/@team)}</win> 
     else if(count($x)>=count($y)) then <win>{$s1}</win> 
     else <win>{$s2}</win>' 
    PASSING PG.goals, PG.home_team AS "s1", PG.visiting_team AS "s2" 
    COLUMNS 
     win VARCHAR2(255) PATH '/win' 
) V 
) T1 
GROUP BY T1.round_num, T1.win 
ORDER BY T1.round_num; 

你能幫我嗎?

回答

1

我可以在XPath中看到的主要問題是使用last();假設目標是按照他們得分的順序,事實並非如此。在第一場比賽中,第62分鐘的節點在第25分鐘的目標之前。你也沒有處理你在第三場比賽中沒有得分的情況。

拉動XML數據進行不同的格式,以使其更易於閱讀:

ROUND_NUM PLAY_DATE HO VI HOME_GOALS HOME_MIN AWAY_GOALS AWAY_MIN LAST_GOAL 
---------- ---------- -- -- ---------- ---------- ---------- ---------- ---------- 
     1 2012-01-01 MI IN   2 25,62    0   MI   
     1 2012-01-02 MI GE   1 30     1 25   MI   
     1 2012-01-03 IN GE   0      0      
     2 2012-01-04 TO JU   0      2 40,90  JU   
     2 2012-01-05 TO SM   3 20,30,50   0   TO   
     2 2012-01-06 JU SM   2 20,40    0   JU   

調整XPath和改變名稱,以使他們多一點有意義的,你可以得到:

select mr.round_num, mr.play_date, mr.home_team, mr.visiting_team, x.win, 
    count(x.win) over (partition by mr.round_num, x.win) as wins 
from matchround mr 
cross join xmltable('let $hg := //player[@team=$h] 
    let $vg := //player[@team=$v] 
    let $lhgm := max(//player[@team=$h]/@minute) 
    let $lvgm := max(//player[@team=$v]/@minute) 
    return if(count($hg)>count($vg)) then <win>{$h}</win> 
     else if(count($vg)>count($hg)) then <win>{$v}</win> 
     else if($lhgm>$lvgm) then <win>{$h}</win> 
     else if($lvgm>$lhgm) then <win>{$v}</win> 
     else <win>{$h}</win>' 
    passing mr.goals, mr.home_team as "h", mr.visiting_team as "v" 
    columns 
    win varchar2(10) path '/win' 
) x 
order by round_num, play_date, home_team; 

ROUND_NUM PLAY_DATE HO VI WIN    WINS 
---------- ---------- -- -- ---------- ---------- 
     1 2012-01-01 MI IN MI     2 
     1 2012-01-02 MI GE MI     2 
     1 2012-01-03 IN GE IN     1 
     2 2012-01-04 TO JU JU     2 
     2 2012-01-05 TO SM TO     1 
     2 2012-01-06 JU SM JU     2 

$lhgm$lvgm是最後的主場/客隊進球分鐘數,從最大值開始。 (不知道他們是否需要首先明確地轉換爲數字;這對於給定的數據是有效的,但是以一位數分鐘進行檢查)。 wins值是每個團隊獲勝次數的分析計數。

然後,您可以看到具有最大數勝:「通過分區」他們是由提供

select round_num, max(win) keep (dense_rank last order by wins) as team 
from (
    select mr.round_num, mr.play_date, mr.home_team, x.win, 
    count(x.win) over (partition by mr.round_num, x.win) as wins 
    from matchround mr 
    cross join xmltable('let $hg := //player[@team=$h] 
     let $vg := //player[@team=$v] 
     let $lhgm := max(//player[@team=$h]/@minute) 
     let $lvgm := max(//player[@team=$v]/@minute) 
     return if(count($hg)>count($vg)) then <win>{$h}</win> 
     else if(count($vg)>count($hg)) then <win>{$v}</win> 
     else if($lhgm>$lvgm) then <win>{$h}</win> 
     else if($lvgm>$lhgm) then <win>{$v}</win> 
     else <win>{$h}</win>' 
    passing mr.goals, mr.home_team as "h", mr.visiting_team as "v" 
    columns 
     win varchar2(10) path '/win' 
) x 
) 
group by round_num 
order by round_num; 

ROUND_NUM TEAM  
---------- ---------- 
     1 MI   
     2 JU   
+0

太感謝你了,我不知道該功能的「保持」,「過」和SQL標準?或者是Oralce的功能? – Mark116

+0

不太清楚老實說標準是什麼;這些也受SQL Server支持,我相信,但我只與Oracle合作。你可以閱讀更多關於[分析功能](http://docs.oracle.com/cd/E11882_01/server.112/e41084/functions004.htm)和[keep last](http://docs.oracle.com/ cd/E11882_01/server.112/e41084/functions083.htm)/ [first](http://docs.oracle.com/cd/E11882_01/server.112/e41084/functions065.htm)。 –