2016-01-21 43 views
-2

Here is the SQL Fiddle link.這裏的HAVING子句實際上在發生什麼?

根據我的理解,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 
+0

您指定了錯誤的MFG。將其更改爲'XYZ' – 2016-01-21 19:59:06

+1

您希望得到什麼輸出?爲什麼? –

回答

2

您當前查詢中的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的文檔。

0

你需要改變您的查詢如下:

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)是在GROUP BY,所以這將返回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 
+0

@anonymous已添加說明。 – Siyual

+0

我並沒有浪費時間在您的解決方案上,我的整個編輯都是爲了解釋爲什麼您的原始查詢沒有返回結果。我的回答有什麼困惑,以便我可以澄清它? – Siyual

+0

這意味着由於只有1個結果,所以一個價格的平均值與價格本身相同。你有條款正在尋找比平均水平更高的東西。由於它們彼此相等,所以它們不能通過'>'檢查。 – Siyual

5

想想這個查詢做你打算工作:

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個。 GROUP BY可以用來計算平均值,但是一旦計算出這個平均值,它就是需要挑選出來的單個行 - 當這些行被聚合到一個組中時無法完成。因此需要兩個獨立的操作 - 一個聚合函數找到平均值,一個選擇挑出感興趣的行。

1

假設您不會總是隻想返回'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' 
0

你被item_typepricemodel分組。這意味着您可以根據item_typepricemodel獲得一個結果行。例如一行item_type = 'BACKPACK'price = 3915.73model = '172-50-2742'。您的表格中是否有相同的item_typepricemodel的兩條記錄?爲此,將它們分組的唯一原因。

對於您要顯示的每個此類行item_type,modelprice,這就是您要分組的三列。沒有其他信息,例如有多少行匹配這些item_typepricemodel,或者該組合的庫存數量。你會得到了與

select distinct item_type, model, price 

然後having子句你相同的結果:price應爲一組更大然後avg(price)。我們再來看看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); 

雖然您比較所有產品的平均值,但這似乎很奇怪。與所有揹包進行比較似乎更自然。爲了做到這一點,你必須將這個標準添加到你的子查詢中。