2015-12-23 2 views
2

Я ищу, чтобы спроектировать запрос, где вычисление сравнивает значение в ячейке со значением в предыдущей ячейке в том же столбце, а другое вычисление использует предыдущий результат вычисления ссылается на предыдущую ячейку для вычисления. Эти данные будут в следующем порядке от образца изображения ниже - Материала, растений и YearWeekSQL Server 2008 R2 - Расчетная ссылка Предыдущая строка

Sample Data Image

с изображением ниже, синие заголовки столбцов представляют исходные данные, а желтые заголовки столбцов представляют расчет строк.

Формулы для расчета строк заключаются в следующем:

  • Во-первых? = ЕСЛИ (И (В2 = В1, С2 = С1), "Нет", "первый")
  • Фактическая Доступные = ЕСЛИ (F2 = "первый", D2-Е2, G1-Е2)

Из моего исследования функции LEAD и LAG могут помочь в этом, но поскольку я ограничен SQL Server 2008 R2, я не могу их использовать. Пожалуйста, найдите запрос для создания таблицы.

CREATE TABLE ZDAYS ([YearWeek] VARCHAR(7), 
    [Material] VARCHAR(3), [Plant] VARCHAR(3), 
    [Inventory] INT, [Demand] INT) 

    INSERT INTO ZDAYS VALUES ('2015-42', 'ABC', '101', 20, 5) 
    INSERT INTO ZDAYS VALUES ('2015-43', 'ABC', '101', 20, 3) 
    INSERT INTO ZDAYS VALUES ('2015-44', 'ABC', '101', 20, 2) 
    INSERT INTO ZDAYS VALUES ('2015-42', 'ABC', '201', 30, 10) 
    INSERT INTO ZDAYS VALUES ('2015-43', 'ABC', '201', 30, 8) 
    INSERT INTO ZDAYS VALUES ('2015-44', 'ABC', '201', 30, 4) 
    INSERT INTO ZDAYS VALUES ('2015-42', 'XYZ', '101', 10, 3) 
    INSERT INTO ZDAYS VALUES ('2015-43', 'XYZ', '101', 10, 2) 
    INSERT INTO ZDAYS VALUES ('2015-44', 'XYZ', '201', 20, 4) 

Окончательный вывод данных

YearWeek Material Plant Inventory Demand First? Actual Available 
2015-42 ABC   101  20  5  First   15    
2015-43 ABC   101  20  3  No   12    
2015-44 ABC   101  20  2  No   10 
2015-42 ABC   201  30  10 First   20 
2015-43 ABC   201  30  8  No   12 
2015-44 ABC   201  30  4  No   8 
2015-42 XYZ   101  10  3  First   7 
2015-43 XYZ   101  10  2  No   5 
2015-44 XYZ   201  20  4  First   16 
+0

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

+0

Привет @GordonLinoff, так как я новичок здесь, можете ли вы сообщить мне формат, в котором вы хотите увидеть окончательные результаты? Я приложил образец образа того, что ожидаю, но не знаю, как публиковать данные здесь в формате строки и столбца. – Shantanu

+0

Вы можете поместить четыре пробела в начале строки, чтобы получить табличный или код. Кроме того, вы можете выделить несколько строк и нажать «{}». –

ответ

1

адаптировано из ответа 'Нет Соединения и нет аналитических функций' по адресу:

http://blog.sqlauthority.com/2011/11/24/sql-server-solution-to-puzzle-simulate-lead-and-lag-without-using-sql-server-2012-analytic-function/

declare @ZDAYS TABLE ([YearWeek] VARCHAR(7), 
    [Material] VARCHAR(3), [Plant] VARCHAR(3), 
    [Inventory] INT, [Demand] INT) 

    INSERT INTO @ZDAYS VALUES ('2015-42', 'ABC', '101', 20, 5) 
    INSERT INTO @ZDAYS VALUES ('2015-43', 'ABC', '101', 20, 3) 
    INSERT INTO @ZDAYS VALUES ('2015-44', 'ABC', '101', 20, 2) 
    INSERT INTO @ZDAYS VALUES ('2015-42', 'ABC', '201', 30, 10) 
    INSERT INTO @ZDAYS VALUES ('2015-43', 'ABC', '201', 30, 8) 
    INSERT INTO @ZDAYS VALUES ('2015-44', 'ABC', '201', 30, 4) 
    INSERT INTO @ZDAYS VALUES ('2015-42', 'XYZ', '101', 10, 3) 
    INSERT INTO @ZDAYS VALUES ('2015-43', 'XYZ', '101', 10, 2) 
    INSERT INTO @ZDAYS VALUES ('2015-44', 'XYZ', '201', 20, 4); 

WITH T1 (RowNum, UniqueID, YearWeek, Material, Plant, Inventory, Demand) 
AS 
    (SELECT Row_Number() OVER(ORDER BY z.Material,z.Plant,z.YearWeek) N 
     ,1.0 + floor(10000 * RAND(convert(varbinary, newid()))) as UniqueID 
     ,z.YearWeek 
     ,z.Material 
     ,z.Plant 
     ,z.Inventory 
     ,z.Demand 
     FROM @ZDAYS z 
    ) 
select T1.*, 
CASE WHEN RowNum%2=1 THEN MAX(CASE WHEN RowNum%2=0 THEN UniqueID END) OVER (Partition BY (RowNum+1)/2) ELSE MAX(CASE WHEN RowNum%2=1 THEN UniqueID END) OVER (Partition BY RowNum/2) END LeadValUniqueID, 
CASE WHEN RowNum%2=1 THEN MAX(CASE WHEN RowNum%2=0 THEN UniqueID END) OVER (Partition BY RowNum/2) ELSE MAX(CASE WHEN RowNum%2=1 THEN UniqueID END) OVER (Partition BY (RowNum+1)/2) END LagValUniqueID 
FROM T1 
ORDER BY T1.Material, T1.Plant, T1.YearWeek 
GO 

или, по той же логике с Lead() и Lag(), конкатенированные для идентификации вместо генерации уникального идентификатора.

declare @ZDAYS TABLE ([YearWeek] VARCHAR(7), 
    [Material] VARCHAR(3), [Plant] VARCHAR(3), 
    [Inventory] INT, [Demand] INT) 

    INSERT INTO @ZDAYS VALUES ('2015-42', 'ABC', '101', 20, 5) 
    INSERT INTO @ZDAYS VALUES ('2015-43', 'ABC', '101', 20, 3) 
    INSERT INTO @ZDAYS VALUES ('2015-44', 'ABC', '101', 20, 2) 
    INSERT INTO @ZDAYS VALUES ('2015-42', 'ABC', '201', 30, 10) 
    INSERT INTO @ZDAYS VALUES ('2015-43', 'ABC', '201', 30, 8) 
    INSERT INTO @ZDAYS VALUES ('2015-44', 'ABC', '201', 30, 4) 
    INSERT INTO @ZDAYS VALUES ('2015-42', 'XYZ', '101', 10, 3) 
    INSERT INTO @ZDAYS VALUES ('2015-43', 'XYZ', '101', 10, 2) 
    INSERT INTO @ZDAYS VALUES ('2015-44', 'XYZ', '201', 20, 4); 

-- LAG and LEAD result rows concatenated 
WITH T1 (RowNum, YearWeek, Material, Plant, Inventory, Demand) 
AS 
    (SELECT Row_Number() OVER(ORDER BY z.Material,z.Plant,z.YearWeek) N 
     ,z.YearWeek 
     ,z.Material 
     ,z.Plant 
     ,z.Inventory 
     ,z.Demand 
     FROM @ZDAYS z 
    ) 
select T1.*, 
CASE WHEN RowNum%2=1 THEN MAX(CASE WHEN RowNum%2=0 THEN YearWeek + ' ' + Material + ' ' + Plant + ' ' + cast(Inventory as varchar(5)) + ' ' + cast(Demand as varchar(5)) END) OVER (Partition BY (RowNum+1)/2) ELSE MAX(CASE WHEN RowNum%2=1 THEN YearWeek + ' ' + Material + ' ' + Plant + ' ' + cast(Inventory as varchar(5)) + ' ' + cast(Demand as varchar(5)) END) OVER (Partition BY RowNum/2) END LeadRowValues, 
CASE WHEN RowNum%2=1 THEN MAX(CASE WHEN RowNum%2=0 THEN YearWeek + ' ' + Material + ' ' + Plant + ' ' + cast(Inventory as varchar(5)) + ' ' + cast(Demand as varchar(5)) END) OVER (Partition BY RowNum/2) ELSE MAX(CASE WHEN RowNum%2=1 THEN YearWeek + ' ' + Material + ' ' + Plant + ' ' + cast(Inventory as varchar(5)) + ' ' + cast(Demand as varchar(5)) END) OVER (Partition BY (RowNum+1)/2) END LagRowValues 
FROM T1 
ORDER BY T1.Material, T1.Plant, T1.YearWeek 
GO 
+0

@Shantanu, пожалуйста, отметьте как это удалось, если это решение сработало для вас. – Shep

+0

Привет, Шеп, я пробовал ваше решение, и оно эмулирует функцию Lag и Lead, но это не окончательное решение, которое я ищу. Проверьте мое последнее редактирование, чтобы увидеть результат, который я ожидаю, т. Е. Столбец «Фактический доступный». – Shantanu

0

В более ранних версиях SQL Server можно использовать apply:

select z.yearweek, z.material, z.plant, z.inventory, z.demand, 
     (case when seqnum = 1 then 'Yes' else 'No' end) as isFirst, 
     (inventory - cume.demand) as ActualAvailable 
from (select z.*, 
      row_number() over (partition by material, plant order by yearweek) as seqnum 
     from zdays z 
    ) z outer apply 
    (select sum(z2.demand) as demand 
     from zdays z2 
     where z2.material = z.material and z2.plant = z.plant and 
      z2.yearweek <= z.yearweek 
    ) cume