【问题标题】:using group by and aggregate function使用分组和聚合函数
【发布时间】:2019-04-17 07:11:14
【问题描述】:

我对 SQL 并不陌生,但由于缺少一些知识,我感觉自己从未完全理解 SQL。我们都知道在使用group by的时候需要用到聚合函数,比如我们有一个orderdetails表(orderid和productid的组合键),写一个查询返回总价值(数量*单价)大于10000的订单,sql为:

select orderid, sum(qty*unitprice) AS totalvalue from Sales.OrderDetails
group by orderid
having sum(qty*unitprice) > 10000

我们知道选择发生在分组和拥有之后,所以当我来到

group by orderid
having sum(qty*unitprice) > 10000

我们已经按照 orderid 对所有记录进行了分组,并总结了所有成本,如果我们可以想象成这样:

orderid  null(a column with no name but contains the total value)

123456   11000.00
987654   12184.00

然后是select子句:

select orderid, sum(qty*unitprice) AS totalvalue

因为我们已经有了 'have' 子句之后的结果, 那么为什么我们需要做 'sum(qty*unitprice)' 来再次做总和,这不是多余的吗?

另外一个让我很困扰的是:在写SQL的时候,select子句在from子句之前,这很不方便,因为你要获取列名的IntelliSense。当然,我可以先从 caluse 开始编写,然后“插入” select 子句,但它使所有内容都以一种逻辑倒退的方式进行。我是唯一有问题的人吗? ...奇怪:(

【问题讨论】:

    标签: sql


    【解决方案1】:

    这肯定是重复的,因此是不可取的,但很难避免重复。您可以使用嵌套查询:

    SELECT orderid, totalvalue
      FROM (SELECT orderid, SUM(qty * unitprice) AS totalvalue
              FROM sales.orderdetails
             GROUP BY orderid) AS order_value
     WHERE totalvalue > 10000
    

    您需要查看 DBMS 的优化器计划,以确定这样做是否会显着降低性能,但它避免了重复 SUM(qty * price) 表达式。理想情况下,优化器会将外部 WHERE 子句作为 HAVING 子句推送到内部查询中,但我不想保证它确实如此(并且不同的系统可能会以不同的方式处理它)。

    【讨论】:

    • 我知道嵌套查询有效,但只是不明白前一种方法的想法。另一个困扰我的是在写SQL时,select子句在from子句之前,这很不方便,因为你想获得列名的IntelliSense,毫无疑问我可以先写from caluse,然后“插入”select子句,这让你的逻辑倒退......奇怪:(
    【解决方案2】:

    首先,有些数据库允许在HAVING中使用别名,所以你可以经常这样写:

    select orderid, sum(qty*unitprice) AS totalvalue
    from Sales.OrderDetails
    group by orderid
    having totalvalue > 10000;
    

    其次,SQL 是一种声明性 语言,而不是过程 语言。也就是说,执行的内容与语句完全不同。实际上,它是一种称为有向无环图的东西(在几乎所有数据库中),它没有您可以从 SQL 关键字中识别的运算符。

    这意味着两个相同的表达式可能只计算一次,即使它们在查询中出现多次。或者在某些情况下,可能根本不计算表达式(例如 exists/not exists 子查询中的 select 表达式)。

    第三,与查询完成的实际工作相比,实际的sum() 计算(在这种情况下)非常小。特别是,性能问题是为聚合安排数据,而不是实际处理聚合函数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-09-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-11
      相关资源
      最近更新 更多