我在尝试理解如何做到这一点时遇到了一些问题。假设我正在进行抽奖。有些门票或一串门票有时会变为无效,我的数据库中将标记为无效标志。每张票也有一个单独的号码,以及transaction id
。
对于报告,我希望将这些无效的门票分成几组。这些组可以是任何大小,可以是1-2或100-560。拥有这些组可以更轻松地丢弃这些票,而不是筛选个别号码。例如,假设我从1-1000卖出1000张票。 Bunches 10-36,100-164和276-340都是无效的。
如何让我的报告显示如下:
Lottery Name| Voided Ticket Series
Lucky 7 | 10-36
Lucky 7 | 100-164
Lucky 7 | 276-340
我有一些表,它们具有以下数据结构。 void票证表如下:
Ticket # | Transaction_ID | Seller_ID |
和交易表:
Transaction_ID | Seller_ID | Asset_ID | Lottery_name
答案 0 :(得分: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>
答案 1 :(得分:0)
对于使用Oracle(但日期)的类似分组想法 - 请参阅http://code.cheesydesign.com/?p=695
我不是特别了解Oracle语法,因此除了CTE方法之外,还有一种更加费力的方法来获得相同的结果(SQL Server语法) - 希望其中一种方法能够为您提供足够的工作。 / p>
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