Мне дан список из 717 SKU, которые я должен пройти и сложить итоговые значения продаж за год и единиц. Я разработал код для поиска SKU по годам и получения общей суммы. Мне было интересно, если бы был способ, которым я мог бы зациклить, чтобы ввести большее количество SKU, чтобы мне не пришлось проходить индивидуальный SKU по SKU.

Я знаком с заявлениями Loop, но не лучший в их выполнении. Интересно, есть ли способ сделать это в Microsoft SQL Server Management Studio 2017.

Я пытался объявить и повторить код, но он был неэффективным.

DECLARE @SDate date
SET @SDate = '01/01/2018'
DECLARE @EDate date
SET @EDate = '12/31/2018'
DECLARE @Sku varchar(20)
SET @Sku = 'SN1580' 


SELECT        SUM(Amount) AS EXPR1
FROM            dbo.[Threshold Enterprises$Sales Invoice Line]
WHERE        ([Shipment Date] BETWEEN @SDate AND @EDate) AND (No_ = N'SN1580')
SELECT        SUM(Quantity) AS EXPR1
FROM            dbo.[Threshold Enterprises$Sales Invoice Line]
WHERE        ([Shipment Date] BETWEEN @SDate AND @EDate) AND (No_ = N'SN1580')

SELECT        SUM(Amount) AS EXPR1
FROM            dbo.[Threshold Enterprises$Sales Invoice Line]
WHERE        ([Shipment Date] BETWEEN @SDate AND @EDate) AND (No_ = N'SN0350')
SELECT        SUM(Quantity) AS EXPR1
FROM            dbo.[Threshold Enterprises$Sales Invoice Line]
WHERE        ([Shipment Date] BETWEEN @SDate AND @EDate) AND (No_ = N'SN0350')

Ожидайте, что результаты дадут мне что-то вроде

SN1234
Amount 1000
Sum 200

SN3456
Amount 2000
Sum 100

Или, если бы был способ получить результаты в формате, который можно легко экспортировать, чтобы преуспеть.

0
adura826 1 Май 2019 в 20:23

3 ответа

Лучший ответ

Не думайте с точки зрения петель. Думайте с точки зрения наборов.

При этом для списка sku используется переменная таблицы, но вы можете использовать CTE, фактическую таблицу, список VALUE; все, что действительно позволяет SQL Server обрабатывать все ваши поисковые термины как набор данных, а не как отдельные входные данные.

DECLARE @SDate date = '01/01/2018'
DECLARE @EDate date = '12/31/2018'

DECLARE @Sku TABLE
(
  Sku varchar(20)
);

INSERT @Sku (Sku)
VALUES (N'SN1580'),
       (N'SN0350'); --<--Add your list here. Maybe use Excel to make the wrappers.

SELECT        
   l.No_ 
  ,SUM(l.Amount) AS Amount
  ,SUM(l.Quantity) AS Quantity
FROM 
  dbo.[Threshold Enterprises$Sales Invoice Line] AS l
  JOIN
   @Sku AS s
    ON s.Sku = l.No_
WHERE
  l.[Shipment Date] BETWEEN @SDate AND @EDate
GROUP BY
  l.No_
2
Eric Brandt 1 Май 2019 в 17:39

Если вам нужно передать несколько SKU, вы можете использовать табличную переменную:

DECLARE @SDate date
SET @SDate = '01/01/2018'
DECLARE @EDate date
SET @EDate = '12/31/2018'

DECLARE @Skus table (SKU varchar(20);

INSERT INTO @SKUs
VALUES('SN1580'),
      ('SN0350');

SELECT SIL.[No_] AS SKU,
       SUM(SIL.Amount) AS Amount,
       SUM(SIL.Quanity) AS Quantity
FROM dbo.[Threshold Enterprises$Sales Invoice Line] SIL --I recommeond against special characters (including white space) in object names
     JOIN @SKUs S ON SIL.[No_] = S.SKU
WHERE SIL.[Shipment Date] BETWEEN @SDate AND @EDate
GROUP BY SIL.[No_];

Если это приложение, использующее этот параметризованный запрос, вам может потребоваться создать определенный пользователем тип таблицы и затем использовать его:

CREATE TYPE dbo.SKUs AS TABLE (SKU varchar(20));

Документация Microsoft описывает, как их использовать, в Табличные параметры.

Отредактируйте, обратите внимание, если ваш столбец [Shipment Date] имеет значения даты и времени (и время может быть значением, отличным от 00:00:00), я рекомендую использовать BETWEEN. Это происходит потому, что в любое время после полуночи последнего дня между этими двумя датами не будет. Например, 2018-04-30 00:00:00.003 не находится между 2018-04-01 и 2018-04-30.

Поэтому если у вас есть значения даты и времени, я предлагаю использовать это предложение:

WHERE SIL.[Shipment Date] >= @SDate
  AND SIL.[Shipment Date] < DATEADD(DAY, 1, @EDate)
5
Larnu 1 Май 2019 в 17:43

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

SELECT      No_ AS SKU, SUM(Amount) AS Amount, SUM(Quantity) AS Quantity
FROM        dbo.[Threshold Enterprises$Sales Invoice Line]
WHERE       ([Shipment Date] BETWEEN @SDate AND @EDate) 
            AND (No_ IN 
                ('SN1580', 'SN0350')
            )
GROUP BY No_;

Или, если у вас есть SKU в таблице, вы можете изменить IN на:

            AND (No_ IN 
                (Select SKU from yourTableHere)
            )
2
Luis Cazares 1 Май 2019 в 17:36