使用连续日期来填充一个日历表很容易:
CREATE TABLE DATE_SEQ(SOME_DATE DATE NOT NULL);
INSERT INTO DATE_SEQ SELECT DATE('01/01/2003') + (ROW_NUMBER()
OVER() - 1) DAYS FROM SYSCAT.COLUMNS;
|
我们已经看到了如何使用 OLAP 函数 ROW_NUMBER() 来创建和填充辅助表。显然,有两种方法可以完成这一任务。例如,我们可以使用递归或者在一个循环中插入记录。在这种解决方案中,使用 ROW_NUMBER 的最大好处是简化了编程。
在接下来的三章中,我们将使用 NUMBER_SEQ 和 DATE_SEQ 这两个辅助表来简化某些本来比较复杂的查询。
使用顺序表打印发票
假设我们需要存储某杂货店一条收银线上的所有销售额。还需要能够打印任何一笔买卖的发票,像这样:
ITEM_NAME PRICE_PER_ITEM
------------------------------ ------------------------
NESCAFE CLASSIC +6.49000000000000E+000
ENGLISH BAGELS 6-PACK +1.49000000000000E+000
ENGLISH BAGELS 6-PACK +1.49000000000000E+000
|
由于某些原因,我们选择不在数据库中存储重复的记录。也就是说,我们希望只存储一条记录 ('ENGLISH BAGELS 6-PACK', 1.49, 2)
,而不是两条记录 ('ENGLISH BAGELS 6-PACK', 1.49)
。
不存储重复行通常可以带来更多方便。因此,我们应该使用下面这样的表:
CREATE TABLE SALE_ITEM(
SALE_ID INT NOT NULL,
ITEM_NAME VARCHAR(30) NOT NULL,
ITEM_QUANTITY SMALLINT NOT NULL,
PRICE_PER_ITEM FLOAT NOT NULL);
INSERT INTO SALE_ITEM VALUES
(1, 'NESCAFE CLASSIC', 1, 6.49),
(1, 'ENGLISH BAGELS 6-PACK', 2, 1.49),
(1, 'BABY CARROTS', 3, 0.99);
|
我们需要编写一个查询,该查询的输出应该是这样的(实际上就是打印一张发票):
ITEM_NAME PRICE_PER_ITEM
------------------------------ ------------------------
NESCAFE CLASSIC +6.49000000000000E+000
ENGLISH BAGELS 6-PACK +1.49000000000000E+000
ENGLISH BAGELS 6-PACK +1.49000000000000E+000
BABY CARROTS +9.90000000000000E-001
BABY CARROTS +9.90000000000000E-001
BABY CARROTS +9.90000000000000E-001
|
下面是一个非常简单的查询,这个查询可以实现上述功能:
SELECT ITEM_NAME, PRICE_PER_ITEM FROM SALE_ITEM JOIN NUMBER_SEQ
ON NUMBER_SEQ.NUM <= SALE_ITEM.ITEM_QUANTITY ORDER BY
PRICE_PER_ITEM DESC
|
注意:在不相等的条件下,联结两个表是完全合法的,像这个例子中就是如此。
如前一章所述,我们也可以通过使用递归来得到所需的结果。在某些情况下,递归或许更加有效。不过,使用了顺序表的代码看上去更简单,更易于理解,并且不必为避免可能由递归招致的无限循环而担忧。因此,在这种情况下,比起使用递归来,使用 ROW_NUMBER 是一种简单的替代方法。