2017-02-14 34 views
1

我有一個在where子句中使用列,但不返回該列的查詢:當我GROUP BY子句中運行這個沒有t1.StoreID爲什麼我必須在group by中包含where子句列?如果我沒有返回該列作爲結果?如何彙總重複結果?

SELECT 
    t1.upc, l1.description, l1.size, 
    l2.Name AS SectionName, l1.section, l3.Name, l1.department, 
    (SELECT SUM(QuantitySold) 
    FROM ProductMovement 
    JOIN ProductsMaster ON ProductsMaster.upc = ProductMovement.upc 
    WHERE TimeID >= (SELECT TimeID 
         FROM Time 
         WHERE FactDate = '1/14/2016') 
     AND TimeID <= (SELECT TimeID 
         FROM Time 
         WHERE FactDate = '1/14/2017') 
     AND ProductsMaster.upc = l1.upc 
     AND (l1.department = 4 OR l1.department = 13) 
     AND (t1.StoreID = 3 OR t1.StoreID = 9 OR t1.StoreID = 2)) AS Qty, 
    (SELECT SUM(TotalSales) 
    FROM ProductMovement 
    JOIN ProductsMaster ON ProductsMaster.upc = ProductMovement.upc 
    WHERE TimeID >= (SELECT TimeID 
         FROM Time 
         WHERE FactDate = '1/14/2016') 
     AND TimeID <= (SELECT TimeID 
         FROM Time 
         WHERE FactDate = '1/14/2017') 
     AND ProductsMaster.upc = l1.upc 
     AND (l1.department = 4 OR l1.department = 13) 
     AND (t1.StoreID = 3 OR t1.StoreID = 9 OR t1.StoreID = 2)) AS Sales 
FROM 
    ProductMovement t1 
JOIN 
    ProductsMaster l1 ON l1.upc = t1.upc 
JOIN 
    EnterpriseSections l2 ON l2.SectionID = l1.section 
JOIN 
    EnterpriseDepartments l3 ON l3.DepartmentID = l1.department 
WHERE 
    (SELECT SUM(QuantitySold) 
    FROM ProductMovement 
    JOIN ProductsMaster ON ProductsMaster.upc = ProductMovement.upc 
    WHERE TimeID >= (SELECT TimeID 
         FROM Time 
         WHERE FactDate = '1/14/2016') 
     AND TimeID <= (SELECT TimeID 
         FROM Time 
         WHERE FactDate = '1/14/2017') 
     AND ProductsMaster.upc = l1.upc 
     AND (l1.department = 4 OR l1.department = 13) 
     AND (t1.StoreID = 3 OR t1.StoreID = 9 OR t1.StoreID = 2)) IS NOT NULL 
GROUP BY 
    l1.upc, t1.upc, l1.section, l2.Name, l1.description, l1.size, l1.department, l3.Name 

我得到的錯誤:

Column 'ProductMovement.StoreID' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

當我將列添加到組中時,我得到每個t1.storeID的重複結果,因爲無論如何我都會彙總所有數據。

爲什麼我需要按列進行分組我沒有返回,我該如何彙總這些結果?

+0

這將有助於解釋您想要實現的目標,最好包括描述您所引用的許多表之間關係的實體關係圖。 –

+0

因爲從技術上講,您不僅在查詢的WHERE子句中使用它,您還在* Column *子查詢的WHERE子句中使用它。列子查詢與列本身具有相同的約束。嘗試將子查詢中的SUM(..)從surrond中移出幷包含子查詢。 – RBarryYoung

回答

0

由於您是「彙總所有數據」,因此您可能需要考慮使用兩個查詢。

第一個查詢:在日期範圍內包含商店3,9和2的所有數據。並將其保存爲臨時表。

第二個查詢:使用您的臨時表作爲輸入。但它大部分與上面所寫的相同,只是沒有對商店進行檢查。

請務必將注意事項留給人們,數據僅爲這3家商店的集合。

將其分解爲兩個步驟將使未來程序員更容易找到此代碼來找出正在發生的事情。

無論是或... 你可以嘗試一個HAVING子句,而不是你的結尾WHERE子句。

SELECT t1.upc, l1.description, l1.size, l2.Name AS SectionName, l1.section, l3.Name, l1.department, 
    SUM(SELECT QuantitySold FROM ProductMovement JOIN ProductsMaster ON 
     ProductsMaster.upc = ProductMovement.upc 
      WHERE TimeID >= (SELECT TimeID FROM Time WHERE FactDate = '1/14/2016') 
      AND TimeID <= (SELECT TimeID FROM Time WHERE FactDate = '1/14/2017') 
      AND ProductsMaster.upc = l1.upc 
      AND (l1.department = 4 OR l1.department = 13) 
      AND (t1.StoreID = 3 OR t1.StoreID = 9 OR t1.StoreID = 2)) AS Qty, 
    SUM(SELECT TotalSales FROM ProductMovement JOIN ProductsMaster ON 
     ProductsMaster.upc = ProductMovement.upc 
     WHERE TimeID >= (SELECT TimeID FROM Time WHERE FactDate = '1/14/2016') 
      AND TimeID <= (SELECT TimeID FROM Time WHERE FactDate = '1/14/2017') 
      AND ProductsMaster.upc = l1.upc AND (l1.department = 4 OR l1.department = 13) 
      AND (t1.StoreID = 3 OR t1.StoreID = 9 OR t1.StoreID = 2)) AS Sales 
    FROM ProductMovement t1 
    JOIN ProductsMaster l1 ON l1.upc = t1.upc 
    JOIN EnterpriseSections l2 ON l2.SectionID = l1.section 
    JOIN EnterpriseDepartments l3 ON l3.DepartmentID = l1.department 
    GROUP BY l1.upc, t1.upc, l1.section, l2.Name, l1.description, l1.size, l1.department, l3.Name 
    HAVING SUM(SELECT QuantitySold FROM ProductMovement JOIN ProductsMaster ON 
      ProductsMaster.upc = ProductMovement.upc 
      WHERE TimeID >= (SELECT TimeID FROM Time WHERE FactDate = '1/14/2016') 
      AND TimeID <= (SELECT TimeID FROM Time WHERE FactDate = '1/14/2017') 
      AND ProductsMaster.upc = l1.upc 
      AND (l1.department = 4 OR l1.department = 13) 
      AND (t1.StoreID = 3 OR t1.StoreID = 9 OR t1.StoreID = 2)) IS NOT NULL 

這將檢查您的Qty總不爲空完成GROUP BY後。 (而不是像WHERE這樣做之前的手。) 這是更忙的代碼,有點難以遵循。如果你有一個小型的數據庫,我推薦兩個查詢解決方案。如果你有一個龐大的數據庫,更大的查詢可能會更快。

祝您好運:)

編輯

還拉你SUM功能,你有他們在選擇之外。因爲你沒有一個GROUP BY選擇那些裏面呢,你是不是聚合他們的那裏。您正在彙總外部選擇。我將修改上面的代碼,將SUM函數拉出到主查詢中。

雖然,我會重申......將查詢拆分爲兩個(如上所述)將通過從第二個查詢中刪除StoreID來解決問題。

+0

謝謝,但此查詢產生相同的錯誤:列'ProductMovement.StoreID'在選擇列表中無效,因爲它不包含在聚合函數或GROUP BY子句中。 – user3839756

+0

Ahhh yes ...很可能你的'SUM'函數需要在你選擇的選擇範圍之外。由於在這些選擇中你沒有'GROUP BY',所以你不會在那裏集合它們。您正在彙總外部選擇。我將修改上面的代碼,將'SUM'函數拉出到主查詢中。 (作爲附註...將查詢分成兩部分將通過從第二個查詢中刪除StoreID來解決問題。) – abraxascarab

0

Why am I required to group by a column [ProductMovement.StoreID] I am not returning

您可能不會返回列,但爲了讓SQL Server來處理您的查詢時,它仍然會需要,因爲你在你的SELECT子句的子查詢有它把它加載到內存中。這是您的查詢,我省略了很多地方爲了簡潔:

SELECT 
    t1.upc, l1.description, l1.size, 
    l2.Name AS SectionName, l1.section, l3.Name, l1.department, 
    (SELECT 
    WHERE 
     -- Here 
     (t1.StoreID = 3 OR t1.StoreID = 9 OR t1.StoreID = 2)) AS Qty, 
    (SELECT 
     -- Here 
     AND (t1.StoreID = 3 OR t1.StoreID = 9 OR t1.StoreID = 2)) AS Sales 
FROM 
    ProductMovement t1 
JOIN 
    ProductsMaster l1 ON l1.upc = t1.upc 
JOIN 
    EnterpriseSections l2 ON l2.SectionID = l1.section 
JOIN 
    EnterpriseDepartments l3 ON l3.DepartmentID = l1.department 
WHERE 
    (SELECT 
     -- Here 
     AND (t1.StoreID = 3 OR t1.StoreID = 9 OR t1.StoreID = 2)) IS NOT NULL 
GROUP BY 
    l1.upc, t1.upc, l1.section, l2.Name, l1.description, l1.size, l1.department, l3.Name 

查找在上面的​​查詢-- Here看到你所引用StoreID。 SQL Server將執行Group by,然後Select,並且由於select子句引用StoreId,因此SQL Server需要在Group by之後保留列。由於您沒有在Group by或集合函數中使用它,因此它不知道如何處理它:如果在引用的select子句中使用子查詢,它如何可能按Group by子句中的某些列進行分組?一個不在組中的列?

0

通常,您應該只添加您在邏輯上分組到GROUP BY的列。我建議不要使用GROUP BY來減少由JOIN引起的結果集中的「意外」重複。對大字符串值進行分組(可能是我想象的ProductsMaster.Description)會不必要地降低性能。

這裏是我會建議實現我假設你正在嘗試做的(在較短的方式)的一種方法:

WITH Movement (
SELECT t1.upc, 
     SUM(t1.QuantitySold) AS 'QuantitySold', 
     SUM(t1.TotalSales) AS 'TotalSales' 
FROM ProductMovement t1 
WHERE t1.StoreID IN (2, 3, 9) 
    AND t1.TimeID >= (SELECT t.TimeID 
        FROM [Time] t 
        WHERE t.FactDate = '1/14/2016') 
    AND t1.TimeID <= (SELECT t.TimeID 
        FROM [Time] t 
        WHERE t.FactDate = '1/14/2017') 
    AND EXISTS (SELECT 1 
       FROM ProductsMaster l1 
       WHERE l1.upc = t1.upc 
       AND l1.department IN (4, 3)) 
GROUP BY t1.upc) 

SELECT m.upc, l1.[description], l1.size, 
     l2.[Name] AS 'SectionName', l1.section, l3.[Name], l1.department, 
     m.QuantitySold, 
     m.TotalSales 
FROM Movement m 
JOIN ProductsMaster l1 ON l1.upc = m.upc 
JOIN EnterpriseSections l2 ON l2.SectionID = l1.section 
JOIN EnterpriseDepartments l3 ON l3.DepartementID = l1.department; 

再次,這是基於大量假設的不知道該實體關係。但是,它應該給你我描述的整體概念。

0

建立在codeyoshi所說的內容上, 您正在通過外部查詢引用對內部查詢聚合進行分組。

select * 
from t1 
inner join 
(select sum(value) 
from ProductMovement 
where (t1.StoreID = 3 OR t1.StoreID = 9 OR t1.StoreID = 2)) 

你的子查詢有對外部列的引用。這是一樣的使用這樣的:

select * 
from t1 
cross join 
(select sum(value), StoreID 
from ProductMovement group by StoreID) as sQuery 
where (t1.StoreID = 3 OR t1.StoreID = 9 OR t1.StoreID = 2) 

更可能的是,你只需要改變你的where子句有點 從這個:

AND ProductsMaster.upc = l1.upc 
    AND (l1.department = 4 OR l1.department = 13) 
    AND (t1.StoreID = 3 OR t1.StoreID = 9 OR t1.StoreID = 2)) IS NOT NULL 

這樣:

AND ProductsMaster.upc = l1.upc) 
    AND (l1.department = 4 OR l1.department = 13) 
    AND (t1.StoreID = 3 OR t1.StoreID = 9 OR t1.StoreID = 2) IS NOT NULL 

雖然我不會感到驚訝,如果你需要通過l1.upc對這個參考進行分組:

AND ProductsMaster.upc = l1.upc 
相關問題