7

좀 더 복잡한 쿼리를 생성하여 SQL 기술을 새로 고치려면 northwind 데이터베이스를 사용하고 있습니다. 불행히도 마지막 사용 사례에 대한 해결책을 찾지 못했습니다. "1997 년 모든 카테고리에서 가장 큰 5 가지 주문의 합계를 구하십시오." 참여집계 함수에서 SQL - 하위 쿼리

테이블은 다음과 같습니다 : 음 ... 그것은 하위 쿼리가 집계 함수에 허용되지 않는 것으로 밝혀졌다 나는 다음과 같은 쿼리

SELECT c.CategoryName, SUM(
    (SELECT TOP 5 od2.UnitPrice*od2.Quantity 
    FROM [Order Details] od2, Products p2 
    WHERE od2.ProductID = p2.ProductID 
    AND c.CategoryID = p2.CategoryID 
    ORDER BY 1 DESC)) 
FROM [Order Details] od, Products p, Categories c, Orders o 
WHERE od.ProductID = p. ProductID 
AND p.CategoryID = c.CategoryID 
AND od.OrderID = o.OrderID 
AND YEAR(o.OrderDate) = 1997 
GROUP BY c.CategoryName 

을 시도

Orders(OrderId, OrderDate) 
Order Details(OrderId, ProductId, Quantity, UnitPrice) 
Products(ProductId, CategoryId) 
Categories(CategoryId, CategoryName) 

. 이 문제에 대한 다른 게시물을 읽었지만 특정 유스 케이스에 대한 해결책을 찾을 수 없습니다. 희망을 당신이 나를 도울 수 있기를 바랍니다 ...

+0

사용중인 RDBMS 버전은 무엇입니까? 또한 주문이 둘 이상의 카테고리에 속할 수 있기 때문에 질문이 정확하지 않습니다. –

+0

MSSQL 2012를 사용하고 있습니다. 하위 쿼리를 참조하는 경우 WHERE 절이 있습니다 (WHERE c.categoryID = p2.CategoryID) - 한 범주 만 필터링해야합니다. – Thomas

답변

20

하위 쿼리는 일반적으로 집계 함수에서 허용되지 않습니다. 대신 내부에 하위 쿼리를 이동하십시오.

SELECT c.CategoryName, 
    (select sum(val) 
    from (SELECT TOP 5 od2.UnitPrice*od2.Quantity as val 
     FROM [Order Details] od2, Products p2 
     WHERE od2.ProductID = p2.ProductID 
     AND c.CategoryID = p2.CategoryID 
     ORDER BY 1 DESC 
     ) t 
) 
FROM [Order Details] od, Products p, Categories c, Orders o 
WHERE od.ProductID = p. ProductID 
AND p.CategoryID = c.CategoryID 
AND od.OrderID = o.OrderID 
AND YEAR(o.OrderDate) = 1997 
GROUP BY c.CategoryName, c.CategoryId 
+0

그 일을 해줘서 고마워! 정보를 위해서 ... CategoryID도 그룹화해야합니다. 마지막 행은'GROUP BY c.CategoryName, c.CategoryID'와 같아야합니다. 하지만 시간 내 주셔서 감사합니다. 쿼리가 정말 이상하게 보입니다. 지금 깊이 분석해야합니다. :) – Thomas

3

분명히 여기에 하위 쿼리 문제는이 (원래는 Access로 작성되었지만 구문은 동일합니다)이며, orderdate = 1997은 1 월 1 일에 대한 주문 날짜를 제공합니다. - datepart (year, orderdate) = 1997가 필요합니다. 각 카테고리에 대해 반환 된 행 (최대 5 개)이 있으면 반환 된 행을 캡슐화하고 집계 할 수 있습니다.

+0

링크를 제공해 주셔서 감사합니다. 네가 맞아 내가 내 글을 편집 했어. YEAR (o.OrderDate) = '1997'' – Thomas

+0

"반환 된 행을 캡슐화하여 집계"에 대한 예제를 제공 할 수 있습니까? – Thomas

+0

SELECT xA, xB, xC, SUM (xd) AS D FROM (열 a, b, c, d, e를 포함하는 유효한 sql select 문) x GROUP BY xd –

3

사용 CTEROW_NUMBER 순위 기능을 대신 과도한 하위 쿼리와이 경우, 당신은 때문에 top 5의 하위 쿼리의 추가 레벨을해야합니다.

;WITH cte AS 
(
    SELECT c.CategoryName, od2.UnitPrice, od2.Quantity, 
     ROW_NUMBER() OVER(PARTITION BY c.CategoryName ORDER BY od2.UnitPrice * od2.Quantity DESC) AS rn 
    FROM [Order Details] od JOIN Products p ON od.ProductID = p.ProductID 
          JOIN Categories c ON p.CategoryID = c.CategoryID 
          JOIN Orders o ON od.OrderID = o.OrderID 
    WHERE o.OrderDate >= DATEADD(YEAR, DATEDIFF(YEAR, 0, '19970101'), 0) 
    AND o.OrderDate < DATEADD(YEAR, DATEDIFF(YEAR, 0, '19970101')+1, 0) 
) 
    SELECT CategoryName, SUM(UnitPrice * Quantity) AS val 
    FROM cte 
    WHERE rn < 6 
    GROUP BY CategoryName 
0

레코드가 날짜순으로 정렬 된 Access 하위 쿼리와 비슷한 문제가 발생했습니다. "Last"집계 함수를 사용했을 때 모든 하위 쿼리를 통과하고 Access 테이블에서 마지막 행의 데이터를 검색하고 정렬 된 쿼리를 검색하지 않았습니다. 이전에 제안 된 것처럼 괄호의 첫 번째 집합 내에서 집계 함수를 사용하도록 쿼리를 다시 작성할 수는 있었지만 쿼리 결과를 원하는 순서대로 정렬 된 데이터베이스의 테이블로 저장하는 것이 더 쉽다는 것을 알았습니다. "집계 함수를 사용하여 원하는 값을 검색 할 수 있습니다. 나중에 결과를 최신으로 유지하기 위해 업데이트 쿼리를 실행합니다. 효율적이지는 않지만 효과적입니다.