Как синтезировать слишком много вызовов SQL в один - PullRequest
0 голосов
/ 04 июня 2019

Настольное приложение vb.net должно выполнять сотни таких вызовов на SQL Server (2012).Объявление составляется в приложении и требует от базы данных сотни (а иногда и тысячи) раз.

Я искал способ объединить вызов в один оператор SQL или хранимую процедуру, если это возможно.

Разницей между одним оператором и другим является переменная "day" (в примере кода '20190724'), которая увеличивается на один день для каждого вызова.

SELECT SUM(table1.qta) 
FROM table1  
WHERE (table1.id = 35)  
  AND ('20190724' BETWEEN table1.date1 AND table1.date2) 

Ожидаемый результатбудет 2 столбца:

day1   SumQta1
day2   SumQta2
day3   SumQta3
....

Ответы [ 2 ]

2 голосов
/ 04 июня 2019

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

Ваш SQL должен выглядеть примерно так:

CREATE TYPE dbo.DatesList
(
    Date Date NOT NULL PRIMARY KEY
);


CREATE PROCEDURE GetSums
(
    @Dates dbo.DatesList readonly
)
AS

SELECT Dates.Date, sum(table1.qta) 
FROM table1 
JOIN @Dates As Dates
    ON Dates.Date BETWEEN table1.date1 AND table1.date2
WHERE table1.id = 35
GROUP BY Dates.Date

Что касается использования таблицы с оценкойпараметр из Vb.Net - Ну, это зависит от того, как вы подключаетесь к базе данных в первую очередь.Я уверен, что здесь есть много ресурсов по stackoverflow, а также в Интернете, чтобы помочь с этой частью.

0 голосов
/ 04 июня 2019

Ну, вы можете создать в своей программе предложение VALUES с интересующими днями. Затем осталось присоединиться к столу и агрегировать, чтобы получить сумму. Вернувшись в свое приложение, вы можете итерировать день результата за день.

SELECT d.day,
       coalesce(sum(t.qta)) qta
       FROM (VALUES ('20190101'),
                    ('20190102'),
                    ...) d (day)
            LEFT JOIN table1 t
                      ON t.id = 35
                         AND d.day BETWEEN t.date1
                                           AND t.date2
       GROUP BY d.day
       ORDER BY d.day;

Другим вариантом может быть использование рекурсивного CTE для генерации дней из минимума и максимума, а затем для этого объединения, снова агрегируя для получения сумм.

WITH
d (day)
AS
(
SELECT convert(date, '20190101') day
UNION ALL
SELECT dateadd(day, 1, day)
       FROM d
       WHERE dateadd(day, 1, day) <= convert(date, '20190131')
)
SELECT d.day,
       coalesce(sum(t.qta)) qta
       FROM d
            LEFT JOIN table1 t
                      ON t.id = 35
                         AND d.day BETWEEN t.date1
                                           AND t.date2
       GROUP BY d.day
       ORDER BY d.day;
...