Oracle SQL通过分隔符

时间:2017-05-26 16:28:32

标签: sql oracle

我正在研究JDBC / Oracle SQL项目,并且遇到了我认为最后的问题。我有一张大型电影及其类别表,如下所示:

Table name = Categories
MovieId          MovieTitle            Category
1                Die Hard              Action|Drama
2                GoodFellas            Drama|Crime

我试图让它看起来像这样:

MovieId          MovieTitle            Category
1                Die Hard              Action
1                Die Hard              Drama
2                Goodfellas            Drama
2                Goodfellas            Crime

这是我一直在玩的一般想法。当我在我的大桌子上运行它似乎无休止地运行时,我在一个较小的桌子上测试它并且它做了我想要的,但是它只显示了Goodfellas的结果而不是Die Hard。请记住,我需要它来更新我的原始表,而不仅仅是创建一个查询。

SELECT distinct MovieId, MovieTitle,REGEXP_SUBSTR(Category,'[^|$]+', 1, LEVEL) Category

FROM Categories

CONNECT BY REGEXP_SUBSTR(Category, '[^|$]+', 1, LEVEL) IS NOT NULL;

感谢任何帮助。我已经浏览了SO上的其他线程,其中很多都处理通过较小的数据表进行排序,而不是像我的那样大。谢谢!

2 个答案:

答案 0 :(得分:2)

您可以在没有正则表达式的情况下尝试递归CTE

WITH result_data (MovieId, MovieTitle, Category, StartPosition, EndPosition) 
     AS (SELECT MovieId, 
                MovieTitle, 
                Category, 
                1, 
                INSTR(Category, '|') 
         FROM   Categories 
         UNION ALL 
         SELECT MovieId, 
                MovieTitle, 
                Category, 
                EndPosition + 1, 
                INSTR(Category, '|', EndPosition + 1) 
         FROM   result_data 
         WHERE  EndPosition > 0) 
SELECT MovieId, 
       MovieTitle, 
       SUBSTR(Category, StartPosition, 
              DECODE(EndPosition, 0, LENGTH(Category) + 1, EndPosition) - StartPosition) AS Category 
FROM   result_data 
ORDER  BY MovieId, StartPosition 

您可以查看演示here

答案 1 :(得分:1)

这是另一种方式。而不是更新,为什么不截断表并重新加载它?

SQL> with Movie(id,title,genre) as (
     select 1, 'Die Hard',   'Action|Drama' from dual union
     select 2, 'GoodFellas', 'Drama|Crime'  from dual
   )
   SELECT Id, title, --column_value substring_nbr,
          regexp_substr(genre, '(.*?)(\||$)', 1, column_value, null, 1) genre
   FROM category,
        TABLE(
          CAST(
            MULTISET(SELECT LEVEL
                     FROM dual
                     CONNECT BY LEVEL <= REGEXP_COUNT(genre, '\|')+1
                     ) AS sys.OdciNumberList
                   )
               )
   ORDER BY Id, title --, substring_nbr
   ;

        ID TITLE      GENRE
---------- ---------- ------------
         1 Die Hard   Action
         1 Die Hard   Drama
         2 GoodFellas Drama
         2 GoodFellas Crime

SQL>

虽然这回答了你的问题,但它不是一个好的数据库设计。我们退一步吧。您有一个具有ID和Title属性的Movie实体,以及一个具有描述ID和描述实体的属性的Genre实体。电影可以有许多类型,许多电影都可以使用一种类型,因此这是一种多对多的关系。为了对其进行建模,您可以从每个实体中获取主键(唯一标识实体实例的属性),并将它们作为外键一起作为所谓的关联表的主键。在这种情况下,我称之为movie_genre。因此,对于您的测试数据,我将使用3个表格对此进行建模:

Movie                  Genre              Movie_Genre
-----                  -----              -----------
movieID  TITLE         genreID  DESC      movieID  genreID
1        Die Hard      1        Action    1        1
2        GoodFellas    2        Drama     1        2
                       3        Crime     2        2
                                          2        2