Группировка чисел из большой группы - PullRequest
0 голосов
/ 03 марта 2012

Я сталкиваюсь с некоторыми проблемами, пытаясь понять, как я могу это сделать.Допустим, я участвую в лотерее.Некоторые билеты или пакеты билетов иногда оказываются недействительными, что будет помечено флагом 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

Ответы [ 2 ]

1 голос
/ 03 марта 2012

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

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 голосов
/ 03 марта 2012

Существует пример того, как найти смежные группы в 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
...