Справка по сложным SQL-запросам - PullRequest
1 голос
/ 14 июня 2011

Я пытаюсь сделать довольно сложный запрос SQL для создания отчета.Это база данных, используемая системой инвентаризации и учета.

По сути, мне нужно создать отчет со следующими столбцами

  • Месяц / Год (группировать результаты по месяцу / году)
  • Торговый посредник (результаты заказа по торговому посреднику с указанием группы месяц / год)
  • Общий объем продаж - Продажи - Оборудование
  • Общий объем продаж - Продажи - Расходные материалы

В отчете необходимо будет использовать следующие таблицы:

  • Счет
  • Торговый посредник
  • Job
  • JobStockItem
  • Stock

По сути, запрос должен начинаться с:
1. Выберите все счета из счета
2. Получите имя посредника из Reseller.Name (присоединитесь к Reseller.ID сInvoice.CustomerID)
3. Получить связанный идентификатор задания из таблицы Job (присоединиться к Job.InvoiceID с Invoice.ID)
4. Получить каждый компонент счета из JobStockItems (присоединиться к JobStockItem.JobID в Job.ID)
5. Получить товар на складе со склада(присоединитесь к JobStockItems.StockId на Stock.ID) и посмотрите, относится ли категория (Stock.Category1) к аппаратным средствам или расходным материалам
6. Если на складе имеется оборудование или расходные материалы, используйте цену продажи в JobStockItem (JobStockItem.PriceExTax) и добавьте его к общей сумме за месяц покупок посредников

Месяц и год берутся из даты выставления счета (Invoice.InvoiceDate).

Теперь я мог бы получить этот результат самостоятельно,выполняю кучу запросов и обрабатываю сам, по одному на каждый из вышеперечисленных этапов, но в конечном итоге он будет медленным, и я уверен, что должен быть запрос, который мог бы обернуть все эти требования и сделать это за один?

Я еще не пытался выполнить запрос, чтобы быть честным, не знаю, с чего начать - это намного сложнее, чем все, что я делал в прошлом.

Я просто использую Management Studio, не использую Reporting Services, Crystal Reports или что-то еще.Моя цель - вывести вывод в HTML, когда он у меня работает.

Заранее спасибо, куча.

Ответы [ 3 ]

4 голосов
/ 14 июня 2011

Думаю, что если вы дважды оставите Join в таблице JobStockItems (один раз для оборудования и один раз для расходных материалов), вы можете управлять всем этим в одном запросе.Окончательный запрос будет выглядеть примерно так (мой редактор пока не работает, поэтому извиняюсь за любые опечатки)

SELECT DATEPART(m, Invoice.InvoiceDate) month, 
       DATEPART(yy, Invoice.InvoiceDate) year, 
       Reseller.Name, 
       SUM(jobstockitems_hardware.Price) sales_hardware,
       SUM(jobstockitems_consumables.Price) sales_consumables, 
FROM Invoice
INNER JOIN Reseller
ON Invoice.CustomerID = Reseller.ID
INNER JOIN Job
ON Invoice.ID = Job.InvoiceID
LEFT JOIN (SELECT JobID, SUM(PriceExTax) Price 
           FROM JobStockItems 
           INNER JOIN Stock 
           ON JobStockItems.StockID = Stock.StockID
           AND Stock.Category1 = 'Hardware'
           GROUP BY JobID) jobstockitems_hardware
ON Job.ID = jobstockitems_hardware.JobID
LEFT JOIN (SELECT JobID, SUM(PriceExTax) Price 
           FROM JobStockItems 
           INNER JOIN Stock 
           ON JobStockItems.StockID = Stock.StockID
           AND Stock.Category1 = 'Consumables'
           GROUP BY JobID) jobstockitems_consumables
ON Job.ID = jobstockitems_consumables.JobID
GROUP BY DATEPART(m, Invoice.Date), 
         DATEPART(yy, Invoice.Date), 
         Reseller.Name
ORDER BY DATEPART(yy, Invoice.Date) ASC, 
         DATEPART(m, Invoice.Date) ASC, 
         Reseller.Name ASC

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

Редактировать: Исправлен запрос на удаление дубликатов

0 голосов
/ 14 июня 2011

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

Мое стандартное решение для этого состоит в том, чтобы взять месяц из таблицы чисел , которая заставляет появляться все периоды времени. Использование запроса DPMattingley в качестве отправной точки -

select
    mths.month,
    mths.year,
    d.Name, 
    d.sales_hardware,
    d.sales_consumables
from
    /*All the in-range months on which to report*/
    (select
        datepart(m,dateadd(m,number,minDate)) month,
        datepart(yy,dateadd(m,number,minDate)) year
    from
        numbers n
            inner join (select min(invoice.invoicedate) as minDate from invoice) m
                on n.number between 0 and datediff(m,minDate,getdate())) mths 

        left join 
            /*Data for each month*/
            (SELECT DATEPART(m, Invoice.InvoiceDate) month, 
                    DATEPART(yy, Invoice.InvoiceDate) year, 
                    Reseller.Name, 
                    SUM(jobstockitems_hardware.Price) sales_hardware,
                    SUM(jobstockitems_consumables.Price) sales_consumables
            FROM 
                Invoice
                    INNER JOIN Reseller
                        ON Invoice.CustomerID = Reseller.ID
                    INNER JOIN Job
                        ON Invoice.ID = Job.InvoiceID
                    LEFT JOIN (SELECT JobID, SUM(PriceExTax) Price 
                               FROM JobStockItems 
                               INNER JOIN Stock 
                               ON JobStockItems.StockID = Stock.StockID
                               AND Stock.Category1 = 'Hardware'
                               GROUP BY JobID) jobstockitems_hardware
                        ON Job.ID = jobstockitems_hardware.JobID
                    LEFT JOIN (SELECT JobID, SUM(PriceExTax) Price 
                               FROM JobStockItems 
                               INNER JOIN Stock 
                               ON JobStockItems.StockID = Stock.StockID
                               AND Stock.Category1 = 'Consumables'
                               GROUP BY JobID) jobstockitems_consumables
                        ON Job.ID = jobstockitems_consumables.JobID
            GROUP BY    DATEPART(m, Invoice.Date), 
                        DATEPART(yy, Invoice.Date), 
                        Reseller.Name) d
                on mths.month=d.month
                and mths.year=d.year

ORDER BY    mths.month ASC, 
            mths.year ASC, 
            Reseller.Name ASC
0 голосов
/ 14 июня 2011

Частично вы хотите PIVOT свои результаты. Таким образом, вы можете просто объединить свои данные и позволить PIVOT выполнять выбор и суммирование категорий:

select  *
from    (
        select  Year = datepart(year, i.InvoiceDate),
                Month = datepart(month, i.InvoiceDate),
                ResellerName = r.name,
                StockCategory = s.Category1,
                jsi.PriceExTax
        from    Invoice i
        inner join Reseller r
            on  r.ID = i.CustomerID
        inner join Job j
            on  j.InvoiceID = i.ID
        inner join JobStockItem jsi
            on  jsi.JobID = j.ID
        inner join Stock s
            on  s.ID = jsi.StockID
        ) d
pivot   (sum(PriceExTax) for StockCategory in (Hardware, Consumables)) p
order by Year, Month, ResellerName;

В конце вам понадобятся некоторые условия во внутреннем запросе (например, где i.InvoiceDate между ...). Возможно, вам нужно умножить PriceExTax на сумму в JobStockItem ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...