XQUERY在多个标签中选择不同的行

时间:2013-04-17 09:43:36

标签: oracle xquery xmltype xmltable

我在oracle中有一个表

create table MOVIE
(MOVIE_ID VARCHAR2(10 BYTE),
TITLE VARCHAR2(50 BYTE),
DIRECTOR VARCHAR2(50 BYTE),
WRITER VARCHAR2(50 BYTE),
GENRE VARCHAR2(50 BYTE),
RELEASE_DATE DATE,
RUNTIME NUMBER,
REVIEWS XMLTYPE);

审核是XML类型

每个评论都有REVIEW(MORE THAN ONE TAG WITH A TAG)的多个标记 我有25个这样的评论,里面有多个评论标记

我想要在不同的行中重复标记的ID

我写了以下查询

SELECT 
XMLQuery(
'for $i in distinct-values (/Reviews/REVIEW/ID)
return data($i)'
PASSING REVIEWS RETURNING CONTENT) ID
FROM MOVIE;

上面的查询给出了输出为 M17 M18 M19如果有相同的REVIEW标签。

我将这三个人排成一排 我想要它们分为3个不同的行。

M17
M18
M19

任何想法都有问题。

1 个答案:

答案 0 :(得分:0)

MOVIE表的XMLTable()联接必须适用于 11g

select 
   m.movie_id,
   id_list.review_id
from 
  movie m,
  XMLTable(
    'for $i in distinct-values($param/Reviews/REVIEW/ID) return $i'
    passing m.reviews as "param"
    columns review_id varchar2(4000) path '//ID'
  ) id_list

但是在 10g 的情况下,它会变得更难,因为这样的构造总是从第一个选定记录中获得REVIEWS字段的值。 使用多重集合的技巧将无法工作并产生相同的结果(从第一个记录中获取值)。

通过将XMLAgg()的所有结果聚合到一个记录中,然后使用XMLTable()从该记录构建新数据集,我找到了 10g 的解决方案。

select
  movie_id,
  review_id
from 
  XMLTable(
    '
      for $movie in $big_root/full_list/movie_entry,
          $review_id in $movie/ID
      return <row><movie_id>{data($movie/@movie_id)}</movie_id><review_id>{$id}</review_id></row> 
    '
    passing 
      (
        select 
          XMLElement("full_list", 
            XMLAgg(
              XMLElement("movie_entry",
                XMLAttributes(m.movie_id as "movie_id"),
                XMLQuery(
                  'for $i in distinct-values($param/Reviews/REVIEW/ID) return $i'
                   passing by value m.reviews as "param"
                   returning content
                ) 
              )
            )
          )
        from 
          movie m
      )
    as "big_root"
    columns 
      movie_id varchar2(4000) path '//row/movie_id',
      review_id varchar2(4000) path '//row/review_id'
  )    

很抱歉,我现在无法测试此查询,但希望它足以让您了解它的外观。

P.S。如果任何人都能解释Oracle 10g的这种行为,如果加入从字段构造的XMLTable(),那就太好了:)