Thursday, April 18, 2013

Одна из опасных ошибок использования внешнего JOIN-а


Если вы не уверены в правильности использования JOIN-ов, не поленитесь решить ее с использованием подзапросами


-- Сколько денег принес каждый товар в мае 1998-го,
-- Способ Join-ами с использованием скобок для избежания ошибок
-- Используем как LEFT так и INNER JOIN
SELECT ProductName, ROUND (SUM (OD.UnitPrice * OD.Quantity * (1-OD.Discount)),2) AS Total
FROM   Products P LEFT JOIN
             (
             [Order Details] OD
             INNER JOIN Orders O
             On OD.OrderID=O.OrderID
             AND YEAR (OrderDate) = 1998
             AND MONTH (OrderDate) = 5
             )
             ON P.ProductID=OD.ProductID
Group by ProductName
Order by Total DESC

----Проверяем результаты использую подзапросы

SELECT ProductName,
             (
             SELECT IsNull  (ROUND (SUM (UnitPrice * Quantity * (1-Discount)),2) ,0)
                    FROM   [Order Details]
                    WHERE  OrderId in
                                  (
                                  SELECT OrderID
                                  FROM Orders
                                  WHERE YEAR (OrderDate) = 1998
                                  AND Month (OrderDate) = 5
                                  )                                
             AND ProductID=Products.ProductID
             ) AS Total
FROM   Products    
Order by Total desc




-- 1. Как зовут продавцов, которые оформили заказов в Берлин больше, чем в Париж
-- 2. Как зовут продавцов, которые оформили заказов в Берлин не меньше, чем в Париж
-- Джойнами
SELECT FirstName + ' ' + LastName, Count (DISTINCT O1.OrderID), Count (Distinct O2.OrderID)
FROM Employees E LEFT JOIN Orders O1
ON     E.EmployeeID=O1.EmployeeID
AND O1.ShipCity='Berlin'
LEFT JOIN Orders O2
ON     E.EmployeeID=O2.EmployeeID
AND O2.ShipCity='Paris'
GROUP BY FirstName + ' ' + LastName
HAVING Count (DISTINCT O1.OrderID) > Count (Distinct O2.OrderID) -- или >= для второй задачи
-- HAVING Count (DISTINCT O1.OrderID) >= Count (Distinct O2.OrderID)

-- Подзапросами
SELECT FirstName + ' ' + LastName
FROM Employees
WHERE
(SELECT Count(ShipCity)
             FROM Orders
             WHERE EmployeeID=Employees.EmployeeID
             AND ShipCity='Berlin'
             )
             > -- или >= для второй задачи
             (SELECT Count(ShipCity)
             FROM Orders
             WHERE EmployeeID=Employees.EmployeeID
             AND ShipCity='Paris'
             )
            

No comments: