2017-02-20 2 views
-1

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

Чтобы обработать эти данные, я должен выполнить цикл while, потому что мне нужно вычислить дату окончания, которая отсутствует на одной таблице.

Датой окончания первой записи должна быть дата начала второй записи -1 день.

Теперь, когда я представляю это моему старшему, он сказал мне, что это большой НЕТ, чтобы использовать цикл внутри хранимой процедуры. И предоставленное решение, что мой старший сделал, создал вид, используя эту таблицу, и создал несколько объединений, чтобы генерировать недостающие данные, которые мне нужны.

Является ли моя петля неправильной? Должен ли я воздерживаться от использования цикла в моей хранимой процедуре в будущем?

+2

SQL-декларативно; хранимые процедуры являются процедурами. Я сделаю все, что в моих силах, чтобы увидеть, могу ли я выполнить требование декларативно, прежде чем прибегать к хранимой процедуре. Нет циклов. – duffymo

+2

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

+0

Вместо использования цикла вы можете использовать оконные выражения ('over ... partition') или использовать сложные объединения. Циклы в 90-процентных случаях не являются хорошей практикой в ​​SQL. – Fka

ответ

1

Всегда рекомендуется использовать подход, основанный на наборе, при работе с проблемами, которые могут потребовать цикла.

Почти всегда ваши циклы while/for можно поменять местами с помощью условных JOIN, чтобы настроить его на основе. Если это счетчик, который вам нужен, попробуйте использовать таблицу подсчета.

Пример цикла преобразуется в Set проблемы с помощью РЕГИСТРИРУЙТЕСЬ как ниже

SELECT DISTINCT A.StartDate, B.EndDate 
FROM 
A LEFT JOIN B 
ON DATEDIFF(d,A.EndDate,B.StartDate)=1 
1

Это всегда лучше, чтобы включить свой код, наряду с данными выборки, чтобы проиллюстрировать ситуацию и описать желаемые результаты с результатом выборки для данных образца. См .: How to post a tsql question on a public forum и How-to-Ask.

Это почти всегда лучше, чтобы избежать каких-либо while или cursor. В описанной ситуации я считаю, что вы можете избежать цикла while или нескольких union запросов, используя функцию окна lead().

Пример использования lead() с common table expression на:

;with cte as (
    select t.* 
    , NextStartDate = lead(StartDate) over (
     partition by ForEachOfThisColumn -- e.g. AccountId, AssignmentId 
     order by StartDate asc 
    ) 
    from t 
) 
select cte.* 
    , EndDate = dateadd(day, -1, NextStartDate) 
from cte; 

Пример использования в производном зрения таблицы/инлайн в lead():

select cte.* 
    , EndDate = dateadd(day, -1, NextStartDate) 
from (
    select t.* 
    , NextStartDate = lead(StartDate) over (
     partition by ForEachOfThisColumn -- e.g. AccountId, AssignmentId 
     order by StartDate asc 
    ) 
    from t 
) as cte;