代码之家  ›  专栏  ›  技术社区  ›  user366312

HAVING子句到底是怎么回事?

  •  -2
  • user366312  · 技术社区  · 9 年前

    Here is the SQL Fiddle link.

    根据我的理解,GROUP BY将返回2个元组。

    MODEL                        ITEM_TYPE                             PRICE
    ---------------------------- ------------------------------------- ----------
    010-99-0101                  BACKPACK                              5329.1 
    626-21-1500                  BACKPACK                              1485.86 
    

    平均价格的值为,

    AVG(PRICE)
    ----------
    4858.014444 
    

    因此,下面的查询应该过滤掉价格的较小值。

    SELECT      item_type, MODEL, items.price
    FROM        ITEMS
    WHERE       MANUFACTURER_NAME = 'UWZ' 
    AND         ITEM_TYPE = 'BACKPACK'
    GROUP   BY item_type, items.price, MODEL
    HAVING      ITEMS.PRICE > AVG(ITEMS.PRICE);
    

    因此,输出应为:

    MODEL                        ITEM_TYPE                             PRICE
    ---------------------------- ------------------------------------- ----------
    010-99-0101                  BACKPACK                              5329.1 
    

    但实际上,以下是输出:

    输出

    no rows selected
    
    5 回复  |  直到 9 年前
        1
  •  5
  •   Steve Chambers    9 年前

    认为此查询符合您的预期:

    SELECT MODEL, ITEM_TYPE, PRICE
    FROM ITEMS
    WHERE MANUFACTURER_NAME = 'UWZ'
      AND ITEM_TYPE = 'BACKPACK'
      AND PRICE > 
          (SELECT AVG(ITEMS.PRICE)
           FROM   ITEMS
           WHERE  MANUFACTURER_NAME = 'UWZ' 
           AND    ITEM_TYPE = 'BACKPACK');
    

    SQL Fiddle demo

    解释

    您尝试使用 GROUP BY 没有达到预期效果。你可以在 this modification 发布查询的 HAVING 子句已被删除,并添加了一列以统计每个组中的项目数: 每个仅1个 . 分组依据 可以用来计算平均值,但一旦计算出平均值,就需要挑出各个行-当它们被聚合到一个组中时,这是无法完成的。因此,需要两个单独的操作- 聚合函数 找到平均值和 选择 选择感兴趣的行。

        2
  •  2
  •   Alex    9 年前

    当前查询中的HAVING子句提取的行的价格大于平均价格 仅针对该行 .

    单个数字的平均值等于该数字,因此不会返回任何行。

    您可以通过将HAVING子句更改为ITEMS来测试这一点。PRICE=AVG(ITEMS.PRICE)-这将返回所有行。

    窗口函数对于这种查询很方便。下面的OVER子句指定AVG_PRICE将平均值应用于给定制造商和项目类型的所有行。

    select  * 
    from    (
        select      MODEL, 
                    ITEM_TYPE, 
                    PRICE, 
                    avg(PRICE) over( 
                       partition by MANUFACTURER_NAME, ITEM_TYPE 
                    ) as AVG_PRICE
        from        ITEMS
        ) as ITEMS_WITH_AVG
    where  PRICE > AVG_PRICE
    

    请参见 amended SQLfiddle

    您可能还想查阅有关 window/analytic functions in Oracle .

        3
  •  1
  •   Simon Ridd    9 年前

    假设您不总是希望只返回“UWZ”和“BACKPACK”的记录,您可以使用下面的查询,该查询使用子查询(派生表)。它建立在史蒂夫·钱伯斯回答中解释的相同原则上,所以我不再重复解释。

    您可以取消注释WHERE子句中的附加条件以返回原始答案。

    SELECT MODEL
         , ITEMS1.ITEM_TYPE
         , ITEMS1.MANUFACTURER_NAME
         , PRICE
    FROM ITEMS ITEMS1
        INNER JOIN (SELECT ITEM_TYPE
                         , MANUFACTURER_NAME
                         , AVG(PRICE) AVG_PRICE
                    FROM   ITEMS
                    GROUP BY ITEM_TYPE
                         , MANUFACTURER_NAME) ITEMS2 
            ON ITEMS1.ITEM_TYPE = ITEMS2.ITEM_TYPE
                AND ITEMS1.MANUFACTURER_NAME = ITEMS2.MANUFACTURER_NAME       
    WHERE PRICE > AVG_PRICE
        --AND ITEMS1.MANUFACTURER_NAME = 'UWZ'
        --AND ITEMS1.ITEM_TYPE = 'BACKPACK'
    
        4
  •  0
  •   Siyual Ranjit Singh    9 年前

    您需要将查询更改为以下内容:

    SELECT      Distinct MODEL, item_type, price
    FROM        ITEMS
    WHERE       MANUFACTURER_NAME = 'UWZ' 
    AND         ITEM_TYPE = 'BACKPACK'
    And         Price > (Select Avg(Price) From Items)
    

    如果你想保留 GROUP BY 出于某种原因,您可以这样做:

    SELECT      MODEL, item_type, items.price
    FROM        ITEMS
    WHERE       MANUFACTURER_NAME = 'UWZ' 
    AND         ITEM_TYPE = 'BACKPACK'
    GROUP BY    item_type, items.price, MODEL
    Having      Price > (Select Avg(Price) From Items)
    

    查询未返回任何结果的原因是 AVG(ITEMS.PRICE) 分组依据 ,所以这将返回 5329.1 .和 5329.1 既不大于也不小于(编辑前的原始查询) 5329.1 。因此,您不会得到任何结果。

    根据我的收集,你正在寻找那些比 AVG 可以通过上面的查询实现。

    您可以通过以下方式自行检查:

    SELECT      item_type, MODEL, items.price, AVG(ITEMS.PRICE) As average
    FROM        ITEMS
    WHERE       MANUFACTURER_NAME = 'UWZ' 
    AND         ITEM_TYPE = 'BACKPACK'
    GROUP   BY  item_type, items.price, MODEL
    

    结果:

    item_type   MODEL       price   average
    ------------------------------------------------
    BACKPACK    010-99-0101 5329.1  5329.1
    
        5
  •  0
  •   Thorsten Kettner    9 年前

    您的分组依据 item_type , price 、和 model 。这意味着你会得到一个结果行 项目类型 , 价格 、和 模型 。例如,一行 item_type = 'BACKPACK' price = 3915.73 model = '172-50-2742' 同一张唱片有两张吗 项目类型 , 价格 、和 模型 在你的桌子上?因为这是将它们分组的唯一原因。

    对于要显示的每一行 项目类型 , 模型 、和 价格 ,这只是您要分组的三列。没有其他信息,例如有多少行与这些信息匹配 项目类型 , 价格 、和 模型 ,或此组合的库存数量。你会得到同样的结果

    select distinct item_type, model, price
    

    然后是你的having条款: 价格 应大于 avg(price) 对于一个组。让我们再次带领团队 价格=3915.73 。价格是3915.73,所有3915.73价格的平均价格当然也是3915.73。你还不如写 having price > price 。当然,价格永远不会高于自身,也永远不会满足标准。相应地,您不会得到结果行。

    你提到的4858.014444的平均价格是表中所有记录的平均价格。因此,您想选择价格高于此价格的所有记录UWZ/BACKPACK记录吗?

    select *
    from items
    where manufacturer_name = 'UWZ' 
    and item_type = 'BACKPACK'
    and price > (select avg(all_items.price) from items all_items);
    

    尽管你把所有产品的平均价格与之相比,这似乎很奇怪。与所有背包相比,这似乎更自然。为了做到这一点,您必须将此条件添加到子查询中。

    推荐文章