存储在数据库中的数据一般不是应用程序所需要的格式,这里举几个例子:
上述情况中,我们需要直接从数据库中检索出转换、计算或格式化后的数据,而不是先检索数据然后再在客户端应用程序中格式化。在这种时候,需要计算字段。
与列不同,计算字段实际上并不存在于数据库表中,是运行时在SELECT语句内创建的。
字段:基本上与列的意思相同,经常互换使用,不过数据库列一般称为列,而术语字段,通常与计算字段仪器使用。
需要特别注意,只有数据库知道SELECT语句中哪些列是实际的表列,哪些列是计算字段。从客户端来看,计算字段的数据与其他列的数据返回方式是相同的。
为了说明如何使用计算字段,举一个简单的例子,创建由两列组成的标题。
Vendors表中包含供应商名ven_name和地址信息vend_country,假如要生成一个供应商报表,需要在一列里列出供应商及其位置,那么需要创建一个组合值,解决办法是将这两列拼接起来。
拼接:将不同的值联结在一起构成单个值。
在SQL中的SELECT语句中,可以使用一个特殊的操作符来拼接两个列,不同的DBMS会采用不同的符号,对于MySQL,则必须使用concat函数。
mysql> SELECT CONCAT(vend_name,'(',vend_country,')')
-> FROM Vendors;
+----------------------------------------+
| CONCAT(vend_name,'(',vend_country,')') |
+----------------------------------------+
| Bear Emporium(USA) |
| Bears R Us(USA) |
| Doll House Inc.(USA) |
| Fun and Games(England) |
| Furball Inc.(USA) |
| Jouets et ours(France) |
+----------------------------------------+
6 rows in set (0.00 sec)
这样的列实际上是没有名字的,只是值,如果要输出到客户端中,这个列就必须有名字,为了解决这个问题,SQL支持别名(alias),用AS关键字赋予:
mysql> SELECT CONCAT(vend_name,'(',vend_country,')') AS vent_title
-> FROM Vendors;
+------------------------+
| vent_title |
+------------------------+
| Bear Emporium(USA) |
| Bears R Us(USA) |
| Doll House Inc.(USA) |
| Fun and Games(England) |
| Furball Inc.(USA) |
| Jouets et ours(France) |
+------------------------+
6 rows in set (0.00 sec)
计算字段的另一常见用途,是对检索出的数据进行算术计算。举个例子,Orders表包含收到的所有订单,OrderItems表包含每个订单中的各项物品。下面的SQL语句检索订单号20008的所有物品:
mysql> SELECT prod_id,quantity,item_price
-> FROM OrderItems
-> WHERE order_num = 20008;
+---------+----------+------------+
| prod_id | quantity | item_price |
+---------+----------+------------+
| RGAN01 | 5 | 4.99 |
| BR03 | 5 | 11.99 |
| BNBG01 | 10 | 3.49 |
| BNBG02 | 10 | 3.49 |
| BNBG03 | 10 | 3.49 |
+---------+----------+------------+
5 rows in set (0.00 sec)
item_price列表示订单中美享尚品的单价,quantity则是商品数,那么,可以加入新的一列,计算所有商品的总价:
mysql> SELECT prod_id,quantity,item_price ,quantity*item_price AS expanded_price
-> FROM OrderItems
-> WHERE order_num = 20008;
+---------+----------+------------+----------------+
| prod_id | quantity | item_price | expanded_price |
+---------+----------+------------+----------------+
| RGAN01 | 5 | 4.99 | 24.95 |
| BR03 | 5 | 11.99 | 59.95 |
| BNBG01 | 10 | 3.49 | 34.90 |
| BNBG02 | 10 | 3.49 | 34.90 |
| BNBG03 | 10 | 3.49 | 34.90 |
+---------+----------+------------+----------------+
5 rows in set (0.00 sec)
与大多数其他计算机语言一样,SQL也可以用函数来处理数据。
与几乎所有DBMS都等同地支持SQL语句不通,每一个DBMS都有特定的函数,事实上,只有少数几个函数被所有主要的DBMS等同第支持,下表列出3个常用的函数及其在各个DBMS中的语法:
可以看到,与SQL语句不一样,SQL函数不是可移植的:为特定SQL实现而编写的代码在其他实现中,可能是不正常的。
例:使用UPPER()函数将文本转换为大写:
mysql> SELECT vend_name,UPPER(vend_name) AS vend_name_upcase
-> FROM Vendors
-> ORDER BY vend_name;
+-----------------+------------------+
| vend_name | vend_name_upcase |
+-----------------+------------------+
| Bear Emporium | BEAR EMPORIUM |
| Bears R Us | BEARS R US |
| Doll House Inc. | DOLL HOUSE INC. |
| Fun and Games | FUN AND GAMES |
| Furball Inc. | FURBALL INC. |
| Jouets et ours | JOUETS ET OURS |
+-----------------+------------------+
6 rows in set (0.00 sec)
下表累出常用的文本处理函数:
日期和时间采用相应的数据类型存储在表中,每种DBMS都有自己的特殊格式,日期和时间值以特殊的格式存储,以便能够快速有效地排序或过滤,并且节省物理存储空间。在不同的DBMS中日期和时间函数是很不一致的,可移植性非常的差。
在Mysql中,可以用YEAR()从日期中提取年份:
mysql> SELECT order_num
-> FROM Orders
-> WHERE YEAR(order_date) = 2012;
+-----------+
| order_num |
+-----------+
| 20005 |
| 20006 |
| 20007 |
| 20008 |
| 20009 |
+-----------+
5 rows in set (0.00 sec)
关于MySQL的日期时间函数具体可以参考:http://www.cnblogs.com/zeroone/archive/2010/05/05/1727659.html
数值处理函数仅仅处理数值数据,这些函数一般主要用于代数、三角或机和运算,是在主要DBMS函数中最一致的函数类型,下表列出常见的数值处理函数:
我们经常需要汇总数据而不用把它们实际检索出来,为此SQL提供了专门的函数,使用这些函数,SQL查询可用于检索数据,这种类型的例子有:
上述例子需要的都是汇总表中的数据,而非实际数据本身。为了方便这种类型的检索,SQL给出了5个聚集函数,列于下表:
AVG()通过对表中行数计数并进而计算列值之和,求得该列的平均值,可用来返回所有列的平均值,也可用来返回特定列或行的平均值。
下例返回Products表中所有产品平均价格:
mysql> SELECT AVG(prod_price) FROM Products;
+-----------------+
| AVG(prod_price) |
+-----------------+
| 6.823333 |
+-----------------+
1 row in set (0.01 sec)
AVG()也可用来确定特定列或行的平均值,下例返回的是特定供应商所提供产品的平均价格:
mysql> SELECT AVG(prod_price) AS avg_price
-> FROM Products
-> WHERE vend_id = 'DLL01'
-> ;
+-----------+
| avg_price |
+-----------+
| 3.865000 |
+-----------+
1 row in set (0.00 sec)
COUNT()函数进行计数,可以确定表中行的数目或符合特定条件的行的数目。
COUNT()函数有两种使用方式:
下例返回Customers表中顾客总数:
mysql> SELECT COUNT(*) FROM Customers;
+----------+
| COUNT(*) |
+----------+
| 5 |
+----------+
1 row in set (0.00 sec)
下例则只对具有电子邮件地址的客户计数:
mysql> SELECT COUNT(cust_email) AS num_cust FROM Customers;
+----------+
| num_cust |
+----------+
| 3 |
+----------+
1 row in set (0.00 sec)
MAX()返回指定列中的最大值,需要注意的是,MAX()必须指定列名,如下所示:
mysql> SELECT MAX(prod_price) AS max_price
-> FROM Products;
+-----------+
| max_price |
+-----------+
| 11.99 |
+-----------+
1 row in set (0.00 sec)
MIN()函数返回指定列中的最小值,同样需要指定列名:
mysql> SELECT MIN(prod_price) AS min_price FROM Products;
+-----------+
| min_price |
+-----------+
| 3.49 |
+-----------+
1 row in set (0.00 sec)
SUM()用来返回指定列值的和(总计)。OrderItems表中包含订单的实际物品,每个物品都有相应的数量,可如下检索所订购物品的总数:
mysql> SELECT SUM(quantity) AS item_ordered
-> FROM OrderItems
-> WHERE order_num = 20005;
+--------------+
| item_ordered |
+--------------+
| 200 |
+--------------+
1 row in set (0.00 sec)
SUM()也可用来合计计算值:
mysql> SELECT SUM(quantity*item_price) AS total_price
-> FROM OrderItems
-> WHERE order_num = 20005;
+-------------+
| total_price |
+-------------+
| 1648.00 |
+-------------+
1 row in set (0.00 sec)
以上5个聚集函数都可以如下使用:
下面的例子使用AVG()函数返回特定供应商提供的产品平均价格,使用了DISTINCT函数:
mysql> SELECT AVG(DISTINCT prod_price) AS avg_price
-> FROM Products
-> WHERE vend_id = 'DLL01';
+-----------+
| avg_price |
+-----------+
| 4.240000 |
+-----------+
1 row in set (0.00 sec)
目前为止的所有聚集函数都只涉及单个函数,但是实际上,SELECT语句可以根据需要包含多个聚集函数,例子如下:
mysql> SELECT COUNT(*) AS num_items,
-> MIN(prod_price) AS price_min,
-> MAX(prod_price) AS price_max,
-> AVG(prod_price) AS price_avg
-> FROM Products;
+-----------+-----------+-----------+-----------+
| num_items | price_min | price_max | price_avg |
+-----------+-----------+-----------+-----------+
| 9 | 3.49 | 11.99 | 6.823333 |
+-----------+-----------+-----------+-----------+
1 row in set (0.00 sec)