Как вставить данные в несколько столбцов из нескольких запросов? - PullRequest
0 голосов
/ 21 марта 2020

Эта SQL Серверная хранимая процедура принимает четыре параметра для отображения порядка таблицы по датам между FromDate и ToDate следующим образом:

CREATE PROCEDURE GetLedger
     (@FromDate date,  
      @ToDate date,  
      @Supplier int,  
      @MOP int)
AS  
BEGIN  
    DECLARE @ExpTABLE TABLE 
                      (  
                          RowNo int,  
                          TranDate date,  
                          NetExpense float
                      )  

    INSERT INTO @ExpTABLE   
        SELECT 
            ROW_NUMBER() OVER (ORDER BY TranDate), TranDate, SUM(NetAmount) 
        FROM 
            Expenditure 
        WHERE
            TranDate BETWEEN @FromDate AND @ToDate 
            AND SupplierID = @Supplier 
            AND MOP = @MOP 
        GROUP BY 
            TranDate  

    DECLARE @Data TABLE
                  (  
                      RDate DATE,  
                      Expense float       
                      PRIMARY KEY (RDate)  
                  )  

    WHILE (@FromDate <= @ToDate)  
    BEGIN  
        INSERT INTO @Data (RDate) 
        VALUES (@FromDate)  

        SELECT @FromDate = DATEADD(DAY, 1, @FromDate)  
    END 

    WHILE (@FromDate <= @ToDate)  
    BEGIN 
        INSERT INTO @Data (Expense) 
            SELECT NetExpense 
            FROM @ExpTABLE 
            WHERE TranDate = @FromDate 

        SELECT @FromDate = DATEADD(DAY, 1, @FromDate)
    END

    SELECT * FROM @Data
END
--EXEC GetLedger '2020-03-01' ,'2020-03-31',2,2

Данные в @ExpTABLE выглядят следующим образом:

RowNo   TranDate    NetExpense
------------------------------
1       2020-03-15  35

Теперь я пытаюсь вставить этот NetExpense '2020-03-15' в таблицу @Data в соответствующую дату, в то время как остальные NetExpense Других дат остаются нулевыми.

Этот INSERT запрос:

WHILE (@FromDate <= @ToDate)  
BEGIN 
    INSERT INTO @Data (Expense) 
        SELECT NetExpense 
        FROM @ExpTABLE 
        WHERE TranDate = @FromDate 

    SELECT @FromDate = DATEADD(DAY, 1, @FromDate)
END

вставляет NULL во все даты, включая '2020-03-15'. Что мне здесь не хватает?

1 Ответ

0 голосов
/ 21 марта 2020

Чтобы иметь строку для каждой даты в вашем диапазоне, было бы полезно использовать таблицу Календаря. Есть много ресурсов о том, как это сделать one . Другой вариант - создать таблицу календаря на лету в виде общего табличного выражения (CTE), например this .

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

DECLARE
    @FromDate DATE
  , @ToDate   DATE
  , @Supplier INT
  , @MOP      INT;

-- set these values to whatever you would pass to your stored procedure
SET @FromDate = '2020-03-01';
SET @ToDate = '2020-03-31';
SET @Supplier = 2;
SET @MOP = 3;

DECLARE @Expenditure TABLE
(
    ID INT NOT NULL
  , TranDate DATE NOT NULL
  , SupplierID INT NOT NULL
  , MOP INT NOT NULL
  , NetAmount DECIMAL(10, 2) NOT NULL
);

INSERT INTO @Expenditure (ID, TranDate, SupplierID, MOP, NetAmount)
VALUES
  (1, '02/28/2020', 2, 3, 200.12)
, (2, '03/15/2020', 2, 3, 125.10)
, (3, '03/15/2020', 2, 3, 74.90)
, (4, '03/17/2020', 3, 3, 150.32)
, (5, '03/18/2020', 2, 3, 250.78)

;WITH cteCalendar (MyDate) AS
(
    SELECT CONVERT(DATE, @FromDate) AS MyDate
    UNION ALL
    SELECT DATEADD(DAY, 1, MyDate)
    FROM   cteCalendar
    WHERE  DATEADD(DAY, 1, MyDate) <= @ToDate
)
SELECT
     ROW_NUMBER() OVER (ORDER BY x.TranDate) AS [RowNo]
   , x.TranDate
   , x.NetExpense
FROM (
         SELECT
                   c.MyDate         AS TranDate
                 , SUM(e.NetAmount) AS [NetExpense]
         FROM      cteCalendar  c
         LEFT JOIN @Expenditure e ON c.MyDate = e.TranDate
                                     AND e.SupplierID = @Supplier
                                     AND e.MOP = @MOP
         GROUP BY  c.MyDate
     ) x;

Вот демо кода.

...