数据库票据库存表TICKET_STOCK有N条数据,例如:
票据类型   票据号
A          20120709001
A          20120709002
A          20120709003
A          20120709011
A          20120709012
A          20120709015
.....省略上万条数据
B          20120709000
B          20120709001
B          20120709002
B          20120709003
B          20120709010
B          20120709011
B          20120709013
B          20120709014
B          20120709015.....省略上万条数据然后我想通过查询得到的数据为:
票据类型      票段
A             20120709001—20120709003
A             20120709011—20120709012
A             20120709015—20120709015
B             20120709000—20120709003
B             20120709010—20120709011
B             20120709013—20120709015备注:最重要的是考虑性能(oracle数据库),目前我已经实现了这种功能,但当数据上千条的时候相当地慢,慢得我无法忍受,跪求高手指点,在下感激不尽!!!!

解决方案 »

  1.   

    SELECT bill_type,
              bill_no
           || '-'
           || DECODE (next_contine_flag, '1', next_bill_no, bill_no)
              fix_bill_no
      FROM (SELECT bill_type,
                   contine_flag,
                   bill_no,
                   LEAD (contine_flag, 1) OVER (ORDER BY bill_type, bill_no)
                      next_contine_flag,
                   LEAD (bill_no, 1) OVER (ORDER BY bill_type, bill_no)
                      next_bill_no
              FROM (SELECT *
                      FROM (SELECT bill_type,
                                   bill_no,
                                   last_bill_type,
                                   last_bill_no,
                                   next_bill_type,
                                   next_bill_no,
                                   (CASE
                                       WHEN (TO_NUMBER (bill_no) - 1) =
                                               TO_NUMBER (last_bill_no)
                                       THEN
                                          '1'
                                       ELSE
                                          '0'
                                    END)
                                      contine_flag
                              FROM (  SELECT bill_type,
                                             bill_no,
                                             LAG (bill_type, 1)
                                                OVER (ORDER BY bill_type, bill_no)
                                                last_bill_type,
                                             LAG (bill_no, 1)
                                                OVER (ORDER BY bill_type, bill_no)
                                                last_bill_no,
                                             LEAD (bill_type, 1)
                                                OVER (ORDER BY bill_type, bill_no)
                                                next_bill_type,
                                             LEAD (bill_no, 1)
                                                OVER (ORDER BY bill_type, bill_no)
                                                next_bill_no
                                        FROM bill_info
                                    ORDER BY bill_type ASC, bill_no ASC))
                     WHERE (last_bill_type IS NULL) OR (next_bill_type IS NULL)
                           OR (bill_type = next_bill_type
                               AND (TO_NUMBER (bill_no) + 1 <>
                                       TO_NUMBER (next_bill_no)))
                           OR (bill_type = next_bill_type
                               AND (TO_NUMBER (bill_no) - 1 <>
                                       TO_NUMBER (last_bill_no)))
                           OR (bill_type <> next_bill_type)))
     WHERE contine_flag = '0'使用如上语句试试,从内向外嵌套语句说明:
    1. 使用Oracle分析函数,将上一行的发票号和下一行的发票号查询出来
    BILL_TYPE | BILL_NO | LAST_BILL_TYPE | LAST_BILL_NO | NEXT_BILL_TYPE | NEXT_BILL_NO
    A    20120709001                        A    20120709002
    A    20120709002    A    20120709001    A    20120709003
    A    20120709003    A    20120709002    A    20120709011
    A    20120709011    A    20120709003    A    20120709012
    A    20120709012    A    20120709011    A    20120709015
    A    20120709015    A    20120709012    B    20120709000
    B    20120709000    A    20120709015    B    20120709001
    B    20120709001    B    20120709000    B    20120709002
    B    20120709002    B    20120709001    B    20120709003
    B    20120709003    B    20120709002    B    20120709010
    B    20120709010    B    20120709003    B    20120709011
    B    20120709011    B    20120709010    B    20120709013
    B    20120709013    B    20120709011    B    20120709014
    B    20120709014    B    20120709013    B    20120709015
    B    20120709015    B    20120709014        2. 第二个select,增加计算字段 contine_flag,标记哪些记录是延续上面的3. 第三个select, 将中间连续的数据过滤掉4. 第四个select, 在上面处理的结果上,再使用分析函数,将依次的下一个BILL_NO查询出来,即
       
    BILL_TYPE | CONTINE_FLAG | BILL_NO | NEXT_CONTINE_FLAG | NEXT_BILL_NO
    A 0 20120709001 1 20120709003
    A 1 20120709003 0 20120709011
    A 0 20120709011 1 20120709012
    A 1 20120709012 0 20120709015
    A 0 20120709015 0 20120709000
    B 0 20120709000 1 20120709003
    B 1 20120709003 0 20120709010
    B 0 20120709010 1 20120709011
    B 1 20120709011 0 20120709013
    B 0 20120709013 1 20120709015
    B 1 20120709015 5. 最后一个语句,将上下的BILL_NO 连起来,去掉 contine_flag = '1' 的,即标记为向上连续的记录
    BILL_TYPE | FIX_BILL_NO
    A 20120709001-20120709003
    A 20120709011-20120709012
    A 20120709015-20120709015
    B 20120709000-20120709003
    B 20120709010-20120709011
    B 20120709013-20120709015
      

  2.   

    with t as (
    select 'A' as ticketType,'20120709001' as ticketCode from dual
    union all
    select 'A','20120709002' from dual
    union all
    select 'A','20120709003' from dual
    union all
    select 'A','20120709011' from dual
    union all
    select 'A','20120709012' from dual
    union all
    select 'A','20120709015' from dual
    union all
    select 'B','20120709000' from dual
    union all
    select 'B','20120709001' from dual
    union all
    select 'B','20120709002' from dual
    union all
    select 'B','20120709003' from dual
    union all
    select 'B','20120709010' from dual
    union all
    select 'B','20120709011' from dual
    union all
    select 'B','20120709013' from dual
    union all
    select 'B','20120709014' from dual
    union all
    select 'B','20120709015' from dual
    )
    select tickettype,min(ticketcode) || '--' || max(ticketcode) from (
    select tickettype,ticketcode,ticketcode -rn as rn from (
    select tickettype,ticketcode,row_number()over(partition by ticketType order by ticketCode) as rn from t
    )
    ) group by rn,tickettype
    order by tickettype,min(ticketcode)TICKETTYPE MIN(TICKETCODE)||'--'||MAX(TICKETCODE) 
    ---------- -------------------------------------- 
    A          20120709001--20120709003               
    A          20120709011--20120709012               
    A          20120709015--20120709015               
    B          20120709000--20120709003               
    B          20120709010--20120709011               
    B          20120709013--20120709015 
      

  3.   

    其实这里用LEAD,lag会慢,一般我处理公司大数据量的话会用ROWNUM来处理,例如
    A 20120709001
    A 20120709002
    A 20120709003
    A 20120709011
    A 20120709012把票号-ROWNUM,得到A 20120709001-1 =20120709000
    A 20120709002-2 =20120709000
    A 20120709003-3 =20120709000
    A 20120709011-4 =20120709007
    A 20120709012-5 =20120709007看到数据了么,相同数据就是连续的记录,然后去相同值的组,后面的知道如何做了吧,不细说了