Построковая обработка sql выборки в сценарии — различия между версиями
Строка 1: | Строка 1: | ||
Если у вас имеется sql-таблица, в которой есть данные, зачастую возникает необходимость в обработке этих данных. Сложность заключается в том, что данные могут быть не пронумерованы или даже если пронумерованы, порядковые номера могут идти не по порядку. | Если у вас имеется sql-таблица, в которой есть данные, зачастую возникает необходимость в обработке этих данных. Сложность заключается в том, что данные могут быть не пронумерованы или даже если пронумерованы, порядковые номера могут идти не по порядку. | ||
− | Возьмем к примеру следующую таблицу notsorted с двумя столбцами | + | Возьмем к примеру следующую таблицу notsorted с двумя столбцами '''id''' и '''name:''' |
Строка 28: | Строка 28: | ||
− | Как видно в таблице id идет не по порядку. При решении данной задачи необходимо учитывать этот факт. | + | Как видно в таблице '''id''' идет не по порядку. При решении данной задачи необходимо учитывать этот факт. |
=== Классический способ решения (не применим) === | === Классический способ решения (не применим) === | ||
Строка 35: | Строка 35: | ||
[[Файл:Обработка таблицы 2.PNG |center]] | [[Файл:Обработка таблицы 2.PNG |center]] | ||
− | В самом начале счетчику i присваивается значение "-1", конечному значению счетчика присваивается количество строк в таблице с помощью запроса: | + | В самом начале счетчику i присваивается значение "'''-1'''", конечному значению счетчика присваивается количество строк в таблице с помощью запроса: |
select @ilast = count(*) from notsorted | select @ilast = count(*) from notsorted | ||
− | Далее реализован цикл, счетчик инкрементируется, затем сравнивается с конечным значением. Выбор значения происходит следующим sql запросом: | + | Далее реализован цикл, счетчик инкрементируется, затем сравнивается с конечным значением. Выбор значения происходит следующим sql-запросом: |
select @name=name from notsorted where id=@id | select @name=name from notsorted where id=@id | ||
Строка 45: | Строка 45: | ||
С полученным значением name производятся действия. | С полученным значением name производятся действия. | ||
− | Результат: | + | '''Результат:''' |
[[Файл:Обработка таблицы 2-1.PNG| center]] | [[Файл:Обработка таблицы 2-1.PNG| center]] | ||
Строка 57: | Строка 57: | ||
− | Начальное значение переменной id_before присваивается "-1000", далее с помощью sql запроса получаем самый первую строку (значения id, name), у которой id > id_before. Записываем id в переменную id_after. В этом же sql запросе получаем количество строк, которые попадают под это условие. Вид запроса: | + | Начальное значение переменной id_before присваивается "-1000", далее с помощью sql-запроса получаем самый первую строку (значения '''id''', ''' name'''), у которой '''id > id_before'''. Записываем '''id''' в переменную '''id_after'''. В этом же sql-запросе получаем количество строк, которые попадают под это условие. Вид запроса: |
− | select top 1 @id=id, @name=name from notsorted where id>@id_before | + | select top 1 @id=id, @name=name from notsorted where id > @id_before |
set @rowcount=@@rowcount | set @rowcount=@@rowcount | ||
− | Если количество строк, у которых условие id> id_before равно нулю (т.е. таких строк нет), то это является индикатором конца цикла. Таким образом в проверке на завершение происходит сравнение rowcount с нулем. Если строки нашлись, то присваиваем id_before текущее значение id_after. Далее совершаем необходимые действия со строкой. | + | Если количество строк, у которых условие '''id > id_before''' равно нулю (т.е. таких строк нет), то это является индикатором конца цикла. Таким образом в проверке на завершение происходит сравнение rowcount с нулем. Если строки нашлись, то присваиваем '''id_before''' текущее значение '''id_after'''. Далее совершаем необходимые действия со строкой. |
− | Результат: | + | '''Результат:''' |
Строка 70: | Строка 70: | ||
− | Недостатки: Если в таблице нет числовых столбцов, то сценарий не применим; если в числовом столбце повторяются значения, то будет обработано только одно из этих значений (в связи с алгоритмом). | + | '''Недостатки:''' Если в таблице нет числовых столбцов, то сценарий не применим; если в числовом столбце повторяются значения, то будет обработано '''только одно''' из этих значений (в связи с алгоритмом). |
Строка 78: | Строка 78: | ||
− | Начальному значению счетчика i присваиваем 0. Конечное значение счетчика ilast равняется количеству строк в таблице, которые необходимо обработать, и находится с помощью sql-запроса: | + | Начальному значению счетчика '''i''' присваиваем '''0'''. Конечное значение счетчика '''ilast''' равняется количеству строк в таблице, которые необходимо обработать, и находится с помощью sql-запроса: |
select @ilast = count(*) from notsorted | select @ilast = count(*) from notsorted | ||
− | Затем счетчик инкрементируется и входит в цикл. Условием окончания цикла является прохождения ilast строк, таким образом если i> ilast, то цикл заканчивает выполняться. Далее необходимо выбрать необходимую строку. Предполагая, что оперируем только со строковым полем предлагается следующий алгоритм. Строки сортируются лексикографически по убыванию, затем выбираются первые i строк. Затем выбирается самая последняя строка (полученная выборка сортируется лексикографически по возрастанию и выбирается первая запись). Таким образом происходит доступ к элементу. | + | Затем счетчик инкрементируется и входит в цикл. Условием окончания цикла является прохождения ilast строк, таким образом если '''i > ilast''', то цикл заканчивает выполняться. Далее необходимо выбрать необходимую строку. Предполагая, что оперируем только со строковым полем предлагается следующий алгоритм. Строки сортируются лексикографически по убыванию, затем выбираются первые '''i''' строк. Затем выбирается самая последняя строка (полученная выборка сортируется лексикографически по возрастанию и выбирается первая запись). Таким образом происходит доступ к элементу. |
− | Так как нет возможности формировать sql запрос динамически (добавив в него переменные), запрос формируется отдельно в строке sql (компонент присвоение). Вид формируемой строки: | + | Так как нет возможности формировать sql-запрос динамически (добавив в него переменные), запрос формируется отдельно в строке '''sql''' (компонент присвоение). Вид формируемой строки: |
'Select Top 1 name as name1 | 'Select Top 1 name as name1 | ||
Строка 94: | Строка 94: | ||
Order by name asc' | Order by name asc' | ||
− | Выполнить данный запрос можно с помощью компонента sql-запрос. При выполнении нужное значение, как видно из запроса, сохраняется в строку name1. Необходимо в сценарии заранее создать переменную с идентичным названием. Строка запроса (в параметрах определяем @sql как строку с запросом sql). | + | Выполнить данный запрос можно с помощью компонента '''sql-запрос'''. При выполнении нужное значение, как видно из запроса, сохраняется в строку '''name1'''. Необходимо в сценарии заранее создать переменную с идентичным названием. Строка запроса (в параметрах определяем '''@sql''' как строку с запросом '''sql'''). |
− | exec sp_executesql @sql | + | exec sp_executesql @sql |
− | Результат: | + | '''Результат:''' |
[[Файл:Обработка таблицы 4-1.PNG | center]] | [[Файл:Обработка таблицы 4-1.PNG | center]] | ||
− | Недостатки: сравнительно с первым вариантом, долгое время выполнения sql-запроса. | + | '''Недостатки:''' сравнительно с первым вариантом, долгое время выполнения sql-запроса. |
− | Достоинства: записи обрабатываются лексикографически; в таблице не обязательно иметь числовое поле - выборку можно сделать по строковым | + | '''Достоинства:''' записи обрабатываются лексикографически; в таблице не обязательно иметь числовое поле - выборку можно сделать '''по строковым полям'''. Это полезно, если у вас нет уникальных идентификаторов в вашей таблице. |
Версия 12:23, 20 сентября 2013
Если у вас имеется sql-таблица, в которой есть данные, зачастую возникает необходимость в обработке этих данных. Сложность заключается в том, что данные могут быть не пронумерованы или даже если пронумерованы, порядковые номера могут идти не по порядку.
Возьмем к примеру следующую таблицу notsorted с двумя столбцами id и name:
id | name |
0 | Иванов Иван |
3 | Петров Петр |
4 | Сергеев Сергей |
5 | Дмитриев Дмитрий |
6 | Алексей Алексей |
Как видно в таблице id идет не по порядку. При решении данной задачи необходимо учитывать этот факт.
Классический способ решения (не применим)
В самом начале счетчику i присваивается значение "-1", конечному значению счетчика присваивается количество строк в таблице с помощью запроса:
select @ilast = count(*) from notsorted
Далее реализован цикл, счетчик инкрементируется, затем сравнивается с конечным значением. Выбор значения происходит следующим sql-запросом:
select @name=name from notsorted where id=@id
С полученным значением name производятся действия.
Результат:
Недостатки: обработка таблицы идет по значению id. Так как в таблице нет строк с id=1, 2 , то сценарий будет делать лишний цикл, выдавать ошибку на sql запросе (или выдавать одно значение несколько раз). Вариант неприменим, если в таблице нет уникального идентификатора, даже если есть некое числовое поле - если у некоторых строк оно одинаковое, то сценарий не сможет вывести эти значения.
Вариант 1 для таблицы с числовым полем
Начальное значение переменной id_before присваивается "-1000", далее с помощью sql-запроса получаем самый первую строку (значения id, name), у которой id > id_before. Записываем id в переменную id_after. В этом же sql-запросе получаем количество строк, которые попадают под это условие. Вид запроса:
select top 1 @id=id, @name=name from notsorted where id > @id_before set @rowcount=@@rowcount
Если количество строк, у которых условие id > id_before равно нулю (т.е. таких строк нет), то это является индикатором конца цикла. Таким образом в проверке на завершение происходит сравнение rowcount с нулем. Если строки нашлись, то присваиваем id_before текущее значение id_after. Далее совершаем необходимые действия со строкой.
Результат:
Недостатки: Если в таблице нет числовых столбцов, то сценарий не применим; если в числовом столбце повторяются значения, то будет обработано только одно из этих значений (в связи с алгоритмом).
Вариант 2 для таблицы со строковыми полями
Начальному значению счетчика i присваиваем 0. Конечное значение счетчика ilast равняется количеству строк в таблице, которые необходимо обработать, и находится с помощью sql-запроса:
select @ilast = count(*) from notsorted
Затем счетчик инкрементируется и входит в цикл. Условием окончания цикла является прохождения ilast строк, таким образом если i > ilast, то цикл заканчивает выполняться. Далее необходимо выбрать необходимую строку. Предполагая, что оперируем только со строковым полем предлагается следующий алгоритм. Строки сортируются лексикографически по убыванию, затем выбираются первые i строк. Затем выбирается самая последняя строка (полученная выборка сортируется лексикографически по возрастанию и выбирается первая запись). Таким образом происходит доступ к элементу.
Так как нет возможности формировать sql-запрос динамически (добавив в него переменные), запрос формируется отдельно в строке sql (компонент присвоение). Вид формируемой строки:
'Select Top 1 name as name1 From ( Select Top ' +Str([i])+ ' name From notsorted Order by name desc ) a Order by name asc'
Выполнить данный запрос можно с помощью компонента sql-запрос. При выполнении нужное значение, как видно из запроса, сохраняется в строку name1. Необходимо в сценарии заранее создать переменную с идентичным названием. Строка запроса (в параметрах определяем @sql как строку с запросом sql).
exec sp_executesql @sql
Результат:
Недостатки: сравнительно с первым вариантом, долгое время выполнения sql-запроса.
Достоинства: записи обрабатываются лексикографически; в таблице не обязательно иметь числовое поле - выборку можно сделать по строковым полям. Это полезно, если у вас нет уникальных идентификаторов в вашей таблице.