2012-03-02 4 views
0

У меня проблемы с попытками понять, как я могу это сделать. Скажем, у меня работает лотерея. Некоторые билеты или пучки билетов иногда оказываются недействительными, и в моей базе данных будет отмечен флаг void. Каждый билет также имеет индивидуальный номер, а также номер transaction id.Группировка номеров из большой группы

Для отчета я хотел бы, чтобы эти аннулированные билеты разделились на группы. Эти группы могут быть любого размера, будь то цифры 1-2 или 100-560. Наличие этих групп делает отбрасывание этих билетов намного проще, чем просеивание для отдельных номеров. Например, скажем, я продаю 1000 билетов, от 1 до 1000. Сгустки 10-36, 100-164 и 276-340 все недействительны.

Как я могу получить свой отчет, чтобы отобразить, что следующим образом:

Lottery Name| Voided Ticket Series 
Lucky 7  | 10-36 
Lucky 7  | 100-164 
Lucky 7  | 276-340 

У меня есть некоторые таблицы на месте, они имеют следующие структуры данных. В таблице недействительных билетов выглядят следующим образом:

Ticket # | Transaction_ID | Seller_ID | 

и сделка таблица:

Transaction_ID | Seller_ID | Asset_ID | Lottery_name 
+0

Вы должны объяснить, какие таблицы у вас есть на месте - например, у вас есть аннулированный билетный столик или вы просите дизайн для этого как часть решения? – kaj

+0

У меня есть все столы, но вы правы, я должен был включить их. Я отредактирую исходный комментарий. – user1245941

+0

Итак, где имя лотереи в этих двух табличных определениях? – kaj

ответ

1

Один из способов сделать это в Oracle, списаны из here:

SQL> CREATE TABLE voided_tix (
    2  ticket_#  NUMBER 
    3 , transaction_id NUMBER 
    4 , seller_id  NUMBER 
    5 ); 

Table created. 

SQL> CREATE TABLE transactions (
    2  transaction_id NUMBER 
    3 , seller_id  NUMBER 
    4 , lottery_name VARCHAR2(20) 
    5 ); 

Table created. 

SQL> INSERT INTO voided_tix 
    2 SELECT CASE 
    3   WHEN ROWNUM BETWEEN 1 AND 27 THEN ROWNUM + 9 
    4   WHEN ROWNUM BETWEEN 28 AND 92 THEN ROWNUM + 72 
    5   WHEN ROWNUM BETWEEN 93 AND 157 THEN ROWNUM + 183 
    6   END 
    7 ,  1000 + ROWNUM 
    8 ,  12345678 
    9 FROM DUAL 
10 CONNECT BY LEVEL <= 157 
11 ; 

157 rows created. 

SQL> INSERT INTO transactions 
    2 SELECT 
    3  1000 + ROWNUM 
    4 , 12345678 
    5 , 'Lucky 7' 
    6 FROM DUAL 
    7 CONNECT BY LEVEL <= 200; 

200 rows created. 

SQL> COL n   FOR 99 
SQL> COL lottery_name FOR A12 
SQL> COL range  FOR A20 
SQL> SELECT ROW_NUMBER() OVER (ORDER BY b.grping) n 
    2 ,  b.lottery_name 
    3 ,  TO_CHAR(MIN(b.ticket_#)) 
    4   || DECODE(MIN(b.ticket_#) 
    5    ,  MAX(b.ticket_#), NULL 
    6    ,  '-' || MAX(b.ticket_#)) range 
    7 FROM (SELECT a.ticket_# 
    8   ,  MAX(a.grp) 
    9     OVER (PARTITION BY a.lottery_name 
10       ,   a.seller_id 
11       ORDER BY  a.ticket_#) grping 
12   ,  a.lottery_name 
13   FROM (SELECT vt.ticket_# 
14     ,  CASE 
15       WHEN vt.ticket_# - 1 <> NVL(LAG(vt.ticket_#) 
16              OVER (PARTITION BY t.lottery_name 
17                ,   vt.seller_id 
18                ORDER BY  vt.ticket_#) 
19             , vt.ticket_#) 
20       THEN vt.ticket_# 
21       END    grp 
22   ,  vt.seller_id 
23   ,  t.lottery_name 
24   FROM voided_tix  vt 
25   ,  transactions t 
26   WHERE vt.seller_id  = t.seller_id 
27   AND  vt.transaction_id = t.transaction_id) a) b 
28 GROUP BY b.grping 
29 ,  b.lottery_name 
30 ORDER BY b.grping 
31 ; 

    N LOTTERY_NAME RANGE 
--- ------------ -------------------- 
    1 Lucky 7  10-36 
    2 Lucky 7  100-164 
    3 Lucky 7  276-340 

SQL> 
0

Существует пример того, как найти смежные группы в https://stackoverflow.com/questions/5424095/efficiently-select-beginning-and-end-of-multiple-contiguous-ranges-in-

Для подобной идеи группирования с использованием Oracle (но даты) - см. http://code.cheesydesign.com/?p=695

Я не знаю конкретно о синтаксисе Oracle, а также о подходах CTE есть более трудоемкий способ получить тот же результат (синтаксис SQL Server) - надеюсь, один из них даст вам достаточно возможностей для работы.

declare @low table 
(
    groupId int identity(1,1), 
    lowRangeId int, 
    lowTicketNumber int 
) 

declare @high table 
(
    groupId int identity(1,1), 
    highRangeId int, 
    highTicketNumber int 
) 


insert into @low (lowRangeId, lowTicketNumber) 
select vdLow.transactionId, vdLow.ticketNumber 
from @voidTickets vdLow 
where not exists (select * from @voidTickets ml where ml.ticketNumber = vdLow.ticketNumber - 1) 

insert into @high (highRangeId, highTicketNumber) 
select vdHigh.transactionId, vdHigh.ticketNumber 
from @voidTickets vdHigh 
where not exists (select * from @voidTickets mh where mh.ticketNumber = vdHigh.ticketNumber + 1) 

select tr.lotteryName, low.lowTicketNumber, high.highTicketNumber 
from @transaction tr 
    inner join @low low on low.lowRangeId = tr.transactionId 
    inner join @high high on high.groupId = low.groupId 
+0

На самом деле это очень помогло. Используя комбинацию первой ссылки, которую вы дали, и вашу информацию здесь, я смог заставить ее работать так, как я предполагал. Спасибо за помощь, я ценю это. – user1245941

Смежные вопросы