Kingbase-查询-表表达式2-WHERE 子句&GROUP BY 和 HAVING 子句

2.2 WHERE 子句
WHERE 子句 SQL WHERE 的语法是
WHERE search_condition
这里的 “search_condition“ 是任意返回一个 boolean 类型值的值表达式(参阅 值表达式 )。
在完成对 FROM 子句的处理之后,生成的虚拟表的每一行都会对根据搜索条件进行检查。如果该条件的结果
是真,那么该行被保留在输出表中;否则(也就是说,如果结果是假或空)就把它抛弃。搜索条件通常至少
要引用一些在 FROM 子句里生成的列;虽然这不是必须的,但如果不引用这些列,那么 WHERE 子句就没什
么用了。
Note: 内连接的连接条件既可以写在 WHERE 子句也可以写在 JOIN 子句里。例如,这些表表达式是等效的:
FROM a, b WHERE a . id = b . id AND b . val > 5
和:
FROM a INNER JOIN b ON (a . id = b . id) WHERE b . val > 5
或者可能还有:
FROM a NATURAL JOIN b WHERE b . val > 5
选择使用哪种只是风格问题。 FROM 子句里的 JOIN 语法可能不那么容易移植到其它 SQL 数据库管理系统
中。对于外部连接而言没有选择:它们必须在 FROM 子句中完成。外部连接的 ON USING 子句不等于
WHERE 条件,因为它导致最终结果中行的增加(对那些不匹配的输入行)和减少。
WHERE 子句的例子:
SELECT ... FROM fdt WHERE c1 > 5
SELECT ... FROM fdt WHERE c1 IN ( 1 , 2 , 3 )
SELECT ... FROM fdt WHERE c1 IN (SELECT c1 FROM t2)
SELECT ... FROM fdt WHERE c1 IN (SELECT c3 FROM t2 WHERE c2 = fdt . c1 + 10 )
SELECT ... FROM fdt WHERE c1 BETWEEN (SELECT c3 FROM t2 WHERE c2 = fdt . c1 + 10 )
AND 100
SELECT ... FROM fdt WHERE EXISTS (SELECT c1 FROM t2 WHERE c2 > fdt . c1)
在上面的例子里, fdt 是从 FROM 子句中派生的表。那些不符合 WHERE 子句的搜索条件的行会被从 fdt
中删除。请注意把标量子查询当做一个值表达式来用。和任何其它查询一样,子查询里可以使用复杂的表表
达式。同时还请注意 fdt 在子查询中也被引用。只有在 c1 也是作为子查询输入表的生成表的列时,才必 须把 c1 限定成 fdt.c1 。但限定列名字可以增加语句的清晰度,即使有时候不是必须的。这个例子展示了
一个外层查询的列名范围如何扩展到它的内层查询。
2.3 GROUP BY HAVING 子句
在通过了 WHERE 过滤器之后,生成的输入表可以使用 GROUP BY 子句进行分组,然后用 HAVING 子句删
除一些分组行。
SELECT select_list
FROM ...
[WHERE ... ]
GROUP BY grouping_column_reference [, grouping_column_reference] ...
GROUP BY 子句被用来把表中在所列出的列上具有相同值的行分组在一起。这些列的列出顺序并没有什么关
系。其效果是把每组具有相同值的行组合为一个组行,它代表该组里的所有行。这样就可以删除输出里的重
复和 / 或计算应用于这些组的聚集。例如:
=> SELECT * FROM test1;
x | y
---+---
a | 3
c | 2
b | 5
a | 1
( 4 rows)
=> SELECT x FROM test1 GROUP BY x;
x
---
a
b
c
( 3 rows)
在第二个查询里,不能写成 SELECT * FROM test1 GROUP BY x ,因为列 y 里没有哪个值可以和每个
组相关联起来。被分组的列可以在选择列表中引用是因为它们在每个组都有单一的值。
通常,如果一个表被分了组,那么没有在 GROUP BY 中列出的列都不能被引用,除非在聚集表达式中被引
用。一个用聚集表达式的例子是:
=> SELECT x, sum (y) FROM test1 GROUP BY x;
x | sum
---+-----
a |
4
b |
5
c |
2
( 3 rows)
这里的 sum 是一个聚集函数,它在整个组上计算出一个单一值。有关可用的聚集函数的更多信息可以在 聚集函数
Tip: 没有聚集表达式的分组实际上计算了一个列中可区分值的集合。也可以用 DISTINCT 子句实现(参阅 DISTINCT )。
此例计算每种产品的总销售额(而不是所有产品的总销售额):
SELECT product_id, p . name, ( sum (s . units) * p . price) AS sales
FROM products p LEFT JOIN sales s USING (product_id)
GROUP BY product_id, p . name, p . price;
在这个例子里,列 product_id p.name p.price 必须在 GROUP BY 子句里,因为它们都在查询的
选择列表里被引用到(但见下文)。列 s.units 不必在 GROUP BY 列表里,因为它只是在一个聚集表达式
sum(...) )里使用,它代表一组产品的销售额。对于每种产品,这个查询都返回一个该产品的所有销售额
的总和行。
如果产品表被建立起来,例如 product_id 是主键,那么在上面的例子中用 product_id 来分组就够了,
因为名称和价格都是函数依赖于产品 ID ,并且关于为每个产品 ID 分组返回哪个名称和价格值就不会有歧义。
在严格的 SQL 里, GROUP BY 只能对源表的列进行分组,但 KingbaseES 把这个扩展为也允许 GROUP BY
根据选择列表中的列分组。也允许对值表达式进行分组,而不仅是简单的列名。
如果一个表已经用 GROUP BY 子句分了组,然后你又只对其中的某些组感兴趣,那么就可以用 HAVING
句,它很象 WHERE 子句,用于从结果中删除一些组。其语法是:
SELECT select_list FROM ... [WHERE ... ] GROUP BY ... HAVING boolean_expression
HAVING 子句中的表达式可以引用分组的表达式和未分组的表达式(后者必须涉及一个聚集函数)。
例子:
=> SELECT x, sum (y) FROM test1 GROUP BY x HAVING sum (y) > 3 ;
x | sum
---+-----
a |
4
b |
5
( 2 rows)
=> SELECT x, sum (y) FROM test1 GROUP BY x HAVING x < 'c' ;
x | sum
---+-----
a |
4
b |
5
( 2 rows)
再次,一个更现实的例子:
SELECT product_id, p . name, ( sum (s . units) * (p . price - p . cost)) AS profit
FROM products p LEFT JOIN sales s USING (product_id)
WHERE s . date > CURRENT_DATE - INTERVAL '4 weeks'
GROUP BY product_id, p . name, p . price, p . cost
HAVING sum (p . price * s . units) > 5000 ;
在上面的例子里, WHERE 子句用那些非分组的列选择数据行(表达式只是对那些最近四周发生的销售为真)。
HAVING 子句限制输出为总销售收入超过 5000 的组。请注意聚集表达式不需要在查询中的所有地方都一
样。
如果一个查询包含聚集函数调用,但是没有 GROUP BY 子句,分组仍然会发生:结果是一个单一行(或者
根本就没有行,如果该单一行被 HAVING 所消除)。它包含一个 HAVING 子句时也是这样,即使没有任何
聚集函数调用或者 GROUP BY 子句。
  • 20
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值