枢轴排序-SQL Oracle

时间:2018-10-12 08:03:00

标签: sql oracle

我有一个像这样的桌子(书):

user_rent | book_rent | rent_from  | rent_to
-----------------------------------------------
Alan Doe  | Macbeth   | 01.07.2018 | 15.07.2018
Alan Doe  | Hamlet    | 16.07.2018 | 01.08.2018
Alan Doe  | Othello   | 02.08.2018 | 31.08.2018
Alan Doe  | King Lear | 01.09.2018 |    
Alex Doe  | Dracula   | 01.07.2018 | 15.07.2018
Alex Doe  | Hamlet    | 16.07.2018 | 01.08.2018
Alex Doe  | Hobbit    | 02.08.2018 | 31.08.2018
Alex Doe  | Inferno   | 01.09.2018 |    
Anna Doe  | 1984      | 01.07.2018 | 15.07.2018
Anna Doe  | King Lear | 16.07.2018 | 01.08.2018
Anna Doe  | Hobbit    | 02.08.2018 | 31.08.2018
Anna Doe  | Dracula   | 01.09.2018 |    
Ella Doe  | Macbeth   | 01.07.2018 | 15.07.2018
Ella Doe  | Beowulf   | 16.07.2018 | 01.08.2018
Ella Doe  | King Lear | 02.08.2018 | 31.08.2018
Ella Doe  | Dracula   | 01.09.2018 |    
Emma Doe  | Beowulf   | 01.07.2018 | 15.07.2018
Emma Doe  | Inferno   | 16.07.2018 | 01.08.2018
Emma Doe  | Macbeth   | 02.08.2018 | 31.08.2018
Emma Doe  | Lolita    | 01.09.2018 |    
Jack Doe  | 1984      | 01.07.2018 | 15.07.2018
Jack Doe  | Inferno   | 16.07.2018 | 01.08.2018
Jack Doe  | Othello   | 02.08.2018 | 31.08.2018
Jack Doe  | Dracula   | 01.09.2018 |
Jade Doe  | Lolita    | 01.07.2018 | 15.07.2018
Jade Doe  | Hobbit    | 16.07.2018 | 01.08.2018
Jade Doe  | Hamlet    | 02.08.2018 | 31.08.2018
Jade Doe  | Beowulf   | 01.09.2018 |    
Jane Doe  | Dracula   | 01.07.2018 | 15.07.2018
Jane Doe  | Ulysses   | 16.07.2018 | 01.08.2018
Jane Doe  | Inferno   | 02.08.2018 | 31.08.2018
Jane Doe  | Pygmalion | 01.09.2018 |
John Doe  | Macbeth   | 01.07.2018 | 15.07.2018
John Doe  | Hobbit    | 16.07.2018 | 01.08.2018
John Doe  | Ulysses   | 02.08.2018 | 31.08.2018
John Doe  | Dracula   | 01.09.2018 |    
Noah Doe  | Pygmalion | 01.07.2018 | 15.07.2018
Noah Doe  | Othello   | 16.07.2018 | 01.08.2018
Noah Doe  | Beowulf   | 02.08.2018 | 31.08.2018
Noah Doe  | 1984      | 01.09.2018 |    
Nora Doe  | Dracula   | 01.07.2018 | 15.07.2018
Nora Doe  | Pygmalion | 16.07.2018 | 01.08.2018
Nora Doe  | Hamlet    | 02.08.2018 | 31.08.2018
Nora Doe  | Lolita    | 01.09.2018 |    
Sara Doe  | Beowulf   | 01.07.2018 | 15.07.2018
Sara Doe  | Dracula   | 16.07.2018 | 01.08.2018
Sara Doe  | Ulysses   | 02.08.2018 | 31.08.2018
Sara Doe  | Lolita    | 01.09.2018 |    
Seth Doe  | Macbeth   | 01.07.2018 | 15.07.2018
Seth Doe  | Hamlet    | 16.07.2018 | 01.08.2018
Seth Doe  | King Lear | 02.08.2018 | 31.08.2018
Seth Doe  | Othello   | 01.09.2018 |

我需要一些租借莎士比亚书籍的用户。

使用此查询:

SELECT USER_RENT,
   COUNT(DISTINCT CASE WHEN BOOK_RENT = 'Hamlet' THEN USER_RENT END) HAMLET,
   COUNT(DISTINCT CASE WHEN BOOK_RENT = 'Othello' THEN USER_RENT END) OTHELLO,
   COUNT(DISTINCT CASE WHEN BOOK_RENT = 'Macbeth' THEN USER_RENT END) MACBETH,
   COUNT(DISTINCT CASE WHEN BOOK_RENT = 'King Lear' THEN USER_RENT END) KING_LEAR
FROM BOOKS
GROUP BY USER_RENT;

我有这个临时表:

user_rent | hamlet | othello | macbeth | king_lear
--------------------------------------------------
Alan Doe  |      1 |       1 |       1 |       1
Alex Doe  |      1 |       0 |       0 |       0
Anna Doe  |      0 |       0 |       0 |       1
Ella Doe  |      0 |       0 |       1 |       1
Emma Doe  |      0 |       0 |       1 |       0
Jack Doe  |      0 |       1 |       0 |       0
Jade Doe  |      1 |       0 |       0 |       0
Jane Doe  |      0 |       0 |       0 |       0
John Doe  |      0 |       0 |       1 |       0
Noah Doe  |      0 |       1 |       0 |       0
Nora Doe  |      1 |       0 |       0 |       0
Sara Doe  |      0 |       0 |       0 |       0
Seth Doe  |      1 |       1 |       1 |       1

我导出到excel然后通过数据透视和过滤器得到了最终的想要的结果(这是我所需要的):

book_rent                  | number
-----------------------------------
Hamlet                     | 5
Othello                    | 4
Macbeth                    | 5
King Lear                  | 4
Hamlet AND Othello         | 2
Hamlet AND Macbeth         | 2
Hamlet AND King Lear       | 2
Othello AND Macbeth        | 1
Othello AND King Lear      | 2
Macbeth AND King Lear      | 3
H AND O AND M              | 2
H AND O AND K              | 2
H AND M AND K              | 2
O AND M AND K              | 2
All four                   | 2
Hamlet OR Othello          | 7
Hamlet OR Macbeth          | 8
.
.
.

由于我的表要大得多,因此为此示例创建了表,是否有更优雅,更简单的方法可以直接在SQL中执行此操作?

2 个答案:

答案 0 :(得分:1)

这是您想要的吗?

SELECT books, COUNT(*)
FROM (SELECT USER_RENT, LISTAGG(BOOK_RENT, ';') WITHIN GROUP (ORDER BY BOOK_RENT) as books
      FROM BOOKS
      GROUP BY USER_RENT
     ) bu
GROUP BY books;

如果某人两次租用同一本书,它会出现多次。您可能需要:

SELECT books, COUNT(*)
FROM (SELECT USER_RENT, LISTAGG(BOOK_RENT, ';') WITHIN GROUP (ORDER BY BOOK_RENT) as books
      FROM (SELECT DISTINCT USER_RENT, BOOK_RENT FROM BOOKS) ub
      GROUP BY USER_RENT
     ) bu
GROUP BY books;

答案 1 :(得分:1)

我的尝试

/* -- sample data 
with titles(book) as (
  select 'Hamlet'    from dual union all
  select 'Othello'   from dual union all
  select 'Macbeth'   from dual union all
  select 'King Lear' from dual ),
books (usr, book) as (
  select 'Alan', 'Hamlet'    from dual union all
  select 'Alan', 'Othello'   from dual union all
  select 'Alan', 'Macbeth'   from dual union all
  select 'Alan', 'King Lear' from dual union all
  select 'Alan', 'Hamlet'    from dual union all
  select 'Alex', 'Hamlet'    from dual union all
  select 'Anna', 'King Lear' from dual union all
  select 'Ella', 'Macbeth'   from dual union all
  select 'Ella', 'King Lear' from dual union all
  select 'Emma', 'Macbeth'   from dual union all
  select 'Jack', 'Othello'   from dual union all
  select 'Jade', 'Hamlet'    from dual union all
  select 'John', 'Macbeth'   from dual union all
  select 'Noah', 'Othello'   from dual union all
  select 'Nora', 'Hamlet'    from dual union all
  select 'Seth', 'Hamlet'    from dual union all
  select 'Seth', 'Othello'   from dual union all
  select 'Seth', 'Macbeth'   from dual union all
  select 'Seth', 'King Lear' from dual ),
*/ -- end of sample data
with 
  tmp as (
    select grp, sys_connect_by_path(book, '#') path, level cnt
      from (select row_number() over (order by book) grp, book from titles) 
      connect by book > prior book),
  groups as (
    select grp, path, cnt, trim(column_value) book 
      from tmp, xmltable(('"'||replace(ltrim(path,'#'), '#', '","')||'"')))
select path, count(1) cnt, listagg(usr, ', ') within group (order by usr) users
  from (
    select usr, path, grp
      from groups g join (select distinct usr, book from books) b on b.book = g.book
      group by usr, path, cnt, grp
      having cnt = count(1))
  group by path

您似乎想要所有书籍组合。我使用了分层查询,然后将函数sys_connect_by_path()的结果分成几行来实现。

下一步是将这些组与表books结合在一起,计算每个用户的图书数量,如果该数量少于该组中的图书数量,请从结果中删除该用户。

最后,我仅对用户进行分组以对其进行计数并以列表形式显示。结果:

PATH                                      CNT USERS
---------------------------------- ---------- -------------------------------
#Hamlet                                     5 Alan, Alex, Jade, Nora, Seth
#Hamlet#King Lear                           2 Alan, Seth
#Hamlet#King Lear#Macbeth                   2 Alan, Seth
#Hamlet#King Lear#Macbeth#Othello           2 Alan, Seth
#Hamlet#King Lear#Othello                   2 Alan, Seth
#Hamlet#Macbeth                             2 Alan, Seth
#Hamlet#Macbeth#Othello                     2 Alan, Seth
#Hamlet#Othello                             2 Alan, Seth
#King Lear                                  4 Alan, Anna, Ella, Seth
#King Lear#Macbeth                          3 Alan, Ella, Seth
#King Lear#Macbeth#Othello                  2 Alan, Seth
#King Lear#Othello                          2 Alan, Seth
#Macbeth                                    5 Alan, Ella, Emma, John, Seth
#Macbeth#Othello                            2 Alan, Seth
#Othello                                    4 Alan, Jack, Noah, Seth