2010-08-11 6 views
2

Ну, я новичок в SQL, поэтому plz извините, если эта проблема слишком новичок для вас. В Northwind (я уверен, что все знают о Northwind) - я пытаюсь получить за каждый месяц продукт, который был продан (по количеству) больше всего и тот, который продавался наименее в 1997 году (заказы usind, детали заказа, таблицы продуктов)SQL-подзапрос/join

Благодарности

UPDATE: Это то, что я до сих пор

Select p.productname, 
     Datepart(MM,o.OrderDate), 
     od.Quantity 
from orders o 
inner join [Order Details] od 
    on o.OrderID = od.OrderID 
inner join Products p 
    on p.ProductID=od.ProductID 
Where YEAR(o.OrderDate)=1997 
Group by Datepart(MM,o.OrderDate), od.Quantity,p.productname 
+5

И какой у вас код или какая часть вы застряли? – HLGEM

+0

Это то, что у меня есть - Но я не могу просмотреть максимальный и минимальный за каждый месяц. . Выберите p.productname, Datepart (MM, o.OrderDate), od.Quantity из заказов o внутреннее соединение [Детали заказа] od on o.OrderID = od.OrderID внутреннее соединение Продукты p на p.ProductID = od.ProductID Где YEAR (o.OrderDate) = 1997 Группа по дате (MM, o.OrderDate), od.Quantity, p. productname – Abey

+0

Abey, вы должны включить информацию в свой последний комментарий в исходный вопрос. Я пошел вперед и сделал это за вас. У вас будет больше удачи в SO, если вы предоставите структуру любых ссылочных таблиц. Я (и большинство людей) знаю, что такое база данных Northwind, но у меня нет запомненной схемы, и я не собираюсь ее искать ... Помогите нам помочь вам. –

ответ

1

У меня есть решение, которое решает вашу проблему. Это отборное заявление с 3 подзапросы, но он работает и имеет наиболее и наименее продаваемый продукт на той же строке:

select 
    a.month, 
    (select top 1 
      p.ProductName as pid 
     from Northwind.dbo.[Order Details] od1 
      left join Northwind.dbo.Orders o on o.OrderID = od1.OrderID 
      left join Northwind.dbo.Products p on p.ProductID = od1.ProductID 
     where 
      YEAR(o.OrderDate)=1997 and 
      DATEPART(MM,o.OrderDate) = a.month 
     group by 
      p.ProductName, 
      DATEPART(MM,o.OrderDate) 
     having 
      sum(od1.Quantity) = MAX(a.qty)), 
    max(a.qty) as maxQty, 
    (select top 1 
      p.ProductName as pid 
     from Northwind.dbo.[Order Details] od1 
      left join Northwind.dbo.Orders o on o.OrderID = od1.OrderID 
      left join Northwind.dbo.Products p on p.ProductID = od1.ProductID 
     where 
      YEAR(o.OrderDate)=1997 and 
      DATEPART(MM,o.OrderDate) = a.month 
     group by 
      p.ProductName, 
      DATEPART(MM,o.OrderDate) 
     having 
      sum(od1.Quantity) = MIN(a.qty)), 
    min(a.qty) as minQty 
from 
    (select 
      p.ProductName as pid, 
      DATEPART(MM,o.OrderDate) as month, 
      sum(od1.Quantity) as qty 
     from Northwind.dbo.[Order Details] od1 
      left join Northwind.dbo.Orders o on o.OrderID = od1.OrderID 
      left join Northwind.dbo.Products p on p.ProductID = od1.ProductID 
     where 
      YEAR(o.OrderDate)=1997 
     group by 
      p.ProductName, 
      DATEPART(MM,o.OrderDate)) as a 
group by 
    a.month 

я уверен, что-то более умный могло бы быть сделано с помощью временных таблиц

+0

Отлично работает. Замечательно. благодаря – Abey

0

трудно сказать, что вы просите, особенно если вы не предоставляют никаких схем для ваших столов. Однако, чтобы начать работу с инструкциями JOIN в SQL, я бы предложил Jeff Atwood's Visual Guide

+0

Дважды в один день Дейв? Вы должны ДЕЙСТВИТЕЛЬНО относиться к этой статье;) –

+0

Ваша точка зрения верна, ИМО. Однако вы можете загрузить эту БД из MS самостоятельно. Этот парень дает инструкции для этого: http://blog.sqlauthority.com/2007/06/15/sql-server-2005-northwind-database-or-adventureworks-database-samples-databases-part-2/ Это проще, чем блог заставляет это звучать. Просто скачайте файл MSI, он распакует sql-скрипт на вашем диске - просто запустите его на своем SQL Server. – Matt

+0

@Matt - Не многие люди (включая меня) пойдут на это усилие. Я просто перейду к другому вопросу, когда собеседник предоставил мне достаточно подробностей, чтобы я мог ответить на их вопрос, не прочесывая сеть. –

2

Это не проблема начинающих. Это обычное дело, но и у одного человека пот довольно трудно получить право. И они часто прибегают к нескольким операторам SQL.

Но вам, друг мой, повезло! Вы собираетесь пойти со мной в мир аналитических функций. Но будьте уверены - есть другие способы справиться с этим, если это не по вашему вкусу.

Я предполагаю, что вы просто возитесь с SQL и достаточно хотите узнать больше. Если вы на самом деле пытаетесь решить конкретную проблему, это поможет, если вы можете быть более конкретным в этих двух пунктах:

  1. Что вы хотите, чтобы ваш результат был похож? Ожидаете ли вы 12 рядов, с колонками «Месяц», «Лучший продавец», «Нижний продавец»? 24 строки в одном результирующем наборе? Являются ли два набора результатов ОК?
  2. Действительно ли «проданы наименее» включают продукты, которые ничего не продавали? (Т.е., они donn't появляются в таблице Order Details за месяц на всех.)

В SQL:

WITH 
    ProductSalesPerMonth AS 
    (
     SELECT 
      DATEPART(MM, O.OrderDate) AS MonthNum, 
      OD.ProductID, 
      SUM(OD.Quantity) AS Quantity 
     FROM 
      Orders O 
      JOIN [Order Details] OD 
      ON O.OrderID = OD.OrderID 
     WHERE 
      O.OrderDate BETWEEN '19970101' AND '19971231' 
     GROUP BY 
      DATEPART(MM, O.OrderDate), 
      OD.ProductID 
    ), 
    RankedProductSalesPerMonth AS 
    (
     SELECT 
      PSPM.*, 
      ROW_NUMBER() OVER (PARTITION BY PSPM.MonthNum ORDER BY PSPM.Quantity ASC) AS Rank_SoldLeast, 
      ROW_NUMBER() OVER (PARTITION BY PSPM.MonthNum ORDER BY PSPM.Quantity DESC) AS Rank_SoldMost 
     FROM 
      ProductSalesPerMonth PSPM 
    ) 
SELECT 
    PS.MonthNum, 
    P.ProductName, 
    PS.Quantity, 
    CASE 
     WHEN Rank_SoldMost = 1 THEN 'Top Seller' 
     WHEN Rank_SoldLeast = 1 THEN 'Bottom Seller' 
     ELSE 'Only Seller' 
    END AS SalesRank 
FROM 
    RankedProductSalesPerMonth PS 
    JOIN Products P 
    ON P.ProductID = PS.ProductID 
WHERE 
    (Rank_SoldMost = 1 OR Rank_SoldLeast = 1) 
ORDER BY 
    MonthNum ASC, 
    Quantity DESC 
; 

Выход:

MonthNum ProductName   Quantity SalesRank 
1  Geitost    119  Top Seller 
1  Konbu     2   Bottom Seller 
2  Pâté chinois   180  Top Seller 
2  Gorgonzola Telino  3   Bottom Seller 
3  Raclette Courdavault 162  Top Seller 
3  Konbu     1   Bottom Seller 

Может быть, вы видя это и говоря «Jeezuz!», так вот краткое объяснение кода.

WITH позволяет вам создать подзапрос, называемый «Common Table Expression». В SQL Server он должен работать как вид. CTE могут ссылаться друг на друга. Я использую их, потому что считаю, что легче понять отдельные компоненты, чем один большой SELECT, где вы ссылаетесь на DATEPART(MM, O.OrderDate) и SUM(OD.Quantity) везде. Это также позволяет нам связывать столы (например, Product), пока нам не понадобится эта информация.

В нашей первой статье мы собираем и суммируем в месяц по каждому продукту. Это все.

Второе предложение определяет продавцов верхнего и нижнего уровня. В SQL Server общий способ найти одну запись из группы - разбивать и сортировать так, чтобы запись, которую вы хотите, попала в верхнюю часть ранжированного списка. Сортируя по количеству DESC, наш главный продавец получит «1» в столбце Ranked_SoldMost. Аналогично для нижнего продавца.

Третье предложение позволяет нам фильтровать до наших продавцов верхнего и нижнего уровня, а затем украшать ProductID информацией о продукте.

И все. Если это не то, о чем вы просили, или у вас есть вопросы, уходите.

+0

Большое вам спасибо за помощь. Действительно ценю это. Да, я сказал, что большой «Jeeeyuz», смотрящий на решение, потратил время на то, чтобы я расшифровал, но имеет для меня идеальный смысл. Спасибо – Abey

+0

Я был вне голосов, когда увидел это вчера, но ваш комментарий к другому ответу просто напомнил мне, что я хотел бы поддержать это. +1 –