今天逛51CTO的oracle版区时候,看到一位午饭发表了类似的求助问题,发现没人讨论和帮助(有点失望对于这一版块,我本人当然是想这一版块可以活跃起来,大家共同并深入去讨论,发现问题解决问题研究问题!),所以自己就研究了一下。

    做统计报表不得不说到SQL的联接,而且SQL的联接是学习oracle数据库的基础中的基础,所以下面简要的
阐述一下理论。
一、概述
    关系理论的3个支柱是选择、投影、联接。使用联接可以将不同表或视图的行相互联系起来。联接支持暗示数据库中存储数据的方式。有几种方法可以联接表的,最常见的方法称为同等联接,该联接依据列值或表达式的相等性将一行与另一个表中的一行或多行关联起来,还可以使用非同等联接来联接表。在这种联接中,行与另一个表中的一行或多行关联起来,前提是这些行的列值在由不等于运算符确定的范围之内。

    另一种不常见的方法是将这些行与同一个表中的其他行关联起来。这种关联建立在列之上,
这些列相互之间有逻辑关系以及层次结构关系。这种联接称为自联接。当执行同等联接和非同等联接时,会排除包含空值或公共联接列中具有不同条目的行。如果有必要的话,可以使用外联接来获得单行。当来自一个表的所有行联接到另一个表的所有行时,就会形成笛卡尔乘积。这种联接通常是
遗漏联接条件或联接条件不充足的结果,但有时也故意为之。

二、联接分类
1、同等联接和非同等联接
2、自联接
3、外联接
(1)左外联接(2)右外联接(3)全外联接

以上关于具体每种联接的含意、示例、用法在这里不做详细说明,更多相关知识可以查看Oracle官方文档。

三、需求场景
看如下图,在数据库里面有两张表,产品价格表和价格范围表,通过编写SQL语句来实现统计报表的效果。

233829884.png


1、创建两张表并插入数据

SQL> desc product_price;
Name    Type         Nullable Default Comments
------- ------------ -------- ------- --------
PRODUCT VARCHAR2(25) Y
PRICE   NUMBER       Y
SQL> desc extend_price;
Name        Type   Nullable Default Comments
----------- ------ -------- ------- --------
START_PRICE NUMBER Y
END_PRICE   NUMBER Y
SQL> select * from product_price;
PRODUCT                        PRICE
------------------------- ----------
a                                  2
b                                  3
c                                 11
d                                 11
e                                 12
f                                 35
g                                 34
h                                 23
i                                 33
j                                 66
k                                 10
11 rows selected
SQL> select * from extend_price;
START_PRICE  END_PRICE
----------- ----------
0          9
10         19
20         29
30         39
40      99999

2、分析
既然是要显示成统计报表的形式内容,那么首先得拿着product_price表的price列值与extend_price
表的start_price/end_price列进行比较才能确定在哪些区间有多少产品

SQL> SELECT
2  CASE
3        WHEN b.start_price || '元到' || b.end_price || '元' LIKE '0%'
4        THEN '10元以下'
5        WHEN b.start_price || '元到' || b.end_price || '元' LIKE '4%'
6        THEN '40元以上'
7        ELSE b.start_price || '元到' || b.end_price || '元'
8        END EXTEND_PRICE,
9        SUM (
10            CASE
11             WHEN a.price >= b.start_price AND a.price <= b.end_price
12                  THEN 1
13                  ELSE 0
14                  END
15            ) PRODUCT_COUNT
16            FROM product_price a, extend_price b
17            WHERE a.price >= b.start_price AND a.price <= b.end_price
18            GROUP BY
19                  CASE
20                          WHEN b.start_price || '元到' || b.end_price || '元' LIKE '0%'
21                          THEN '10元以下'
22                          WHEN b.start_price || '元到' || b.end_price || '元' LIKE '4%'
23                          THEN '40元以上'
24                          ELSE b.start_price || '元到' || b.end_price || '元'
25                          END ORDER BY 1;
EXTEND_PRICE                                                                     PRODUCT_COUNT
-------------------------------------------------------------------------------- -------------
10元以下                                                                                     2
10元到19元                                                                                   4
20元到29元                                                                                   1
30元到39元                                                                                   3
40元以上                                                                                     1
SQL>

3、讨论

假设某一结果集:

月份 、功率分布情况、数量
2013-01 功率小于70     30
2013-01 功率70         21
2013-01 功率71         30
2013-01 功率72         35
2013-01 功率73         40
2013-01 功率74         44
2013-01 功率75         41
2013-01 功率大于75     40

你认为产生这种结果集的表应该怎么样设计才更好?

希望大家可以相互讨论一翻,应该还有比较好的设计或写法的。