Вопрос или проблема
Я хотел бы разобрать каждый столбец из SQL:
SELECT
promzag.skl_sifra_skl skl_sifra_skl, promstavke.art_sifra_art art_sifra_art,
SUM(decode(d.identifikacija, '17', decode(d.knjiz_dok, '3', 0, '1', 0, decode(d.zal_dok, '+', promstavke.kolic_prst, -promstavke.kolic_prst)), 0)) pockol_sta,
SUM(decode(d.identifikacija, '17', decode(d.knjiz_dok, '3', 0, '0', 0, decode(d.zal_dok, '+', decode(skladista.vrsta_cijene, 'NAB', promstavke.faktcij_prst - NVL(promstavke.rabat_prst, 0) + NVL(promstavke.trosz_prst, 0) + NVL(promstavke.troso_prst, 0), 'PBP', promstavke.vrijed_prst - promstavke.porezi_prst, promstavke.vrijed_prst), -decode(skladista.vrsta_cijene, 'NAB', promstavke.faktcij_prst - NVL(promstavke.rabat_prst, 0) + NVL(promstavke.trosz_prst, 0) + NVL(promstavke.troso_prst, 0), 'PBP', promstavke.vrijed_prst - promstavke.porezi_prst, promstavke.vrijed_prst) ) ), 0) ) pocvrij_sta,
SUM(decode(d.knjiz_dok, '3', 0, '1', 0, decode(d.zal_dok, '+', promstavke.kolic_prst, -promstavke.kolic_prst)) ) trenkol_sta,
SUM(decode(d.knjiz_dok, '3', 0, '0', 0, decode(d.zal_dok, '+', decode(skladista.vrsta_cijene, 'NAB', promstavke.faktcij_prst - NVL(promstavke.rabat_prst, 0) + NVL(promstavke.trosz_prst, 0) + NVL(promstavke.troso_prst, 0), 'PBP', promstavke.vrijed_prst - promstavke.porezi_prst, promstavke.vrijed_prst), -decode(skladista.vrsta_cijene, 'NAB', promstavke.faktcij_prst - NVL(promstavke.rabat_prst, 0) + NVL(promstavke.trosz_prst, 0) + NVL(promstavke.troso_prst, 0), 'PBP', promstavke.vrijed_prst - promstavke.porezi_prst, promstavke.vrijed_prst)) ) ) trenvrij_sta,
stanje.cij_sta cij_sta, promzag.pgod_prz prz_pgod_prz,
stanje.napomena_sta napomena_sta, stanje.minzal_sta minzal_sta,
stanje.maxzal_sta maxzal_sta, stanje.trenikol_sta trenikol_sta,
stanje.trenicij_sta trenicij_sta, stanje.trenivrij_sta trenivrij_sta,
SUM(decode(d.ul_izl_dok, 'U', decode(d.knjiz_dok, '3', 0, '1', 0, decode(d.zal_dok, '+', promstavke.kolic_prst, -promstavke.kolic_prst)), 0)) kolicina_ulaz,
abs(SUM(decode(d.ul_izl_dok, 'I', decode(d.knjiz_dok, '3', 0, '1', 0, decode(d.zal_dok, '+', promstavke.kolic_prst, -promstavke.kolic_prst)), 0))) kolicina_izlaz,
SUM(decode(d.ul_izl_dok, 'U', decode(d.knjiz_dok, '3', 0, '0', 0, decode(d.zal_dok, '+', promstavke.vrijed_prst, -promstavke.vrijed_prst)), 0)) vrijed_ulaz,
abs(SUM(decode(d.ul_izl_dok, 'I', decode(d.knjiz_dok, '3', 0, '0', 0, decode(d.zal_dok, '+', promstavke.vrijed_prst, -promstavke.vrijed_prst)), 0))) vrijed_izlaz
FROM tablex
где результат должен быть массивом, т.е.
promzag.skl_sifra_skl skl_sifra_skl,
promstavke.art_sifra_art art_sifra_art,
SUM(decode(d.identifikacija, '17', decode(d.knjiz_dok, '3', 0, '1', 0, decode(d.zal_dok, '+', promstavke.kolic_prst, -promstavke.kolic_prst)), 0)) pockol_sta,
SUM(decode(d.identifikacija, '17', decode(d.knjiz_dok, '3', 0, '0', 0, decode(d.zal_dok, '+', decode(skladista.vrsta_cijene, 'NAB', promstavke.faktcij_prst - NVL(promstavke.rabat_prst, 0) + NVL(promstavke.trosz_prst, 0) + NVL(promstavke.troso_prst, 0), 'PBP', promstavke.vrijed_prst - promstavke.porezi_prst, promstavke.vrijed_prst), -decode(skladista.vrsta_cijene, 'NAB', promstavke.faktcij_prst - NVL(promstavke.rabat_prst, 0) + NVL(promstavke.trosz_prst, 0) + NVL(promstavke.troso_prst, 0), 'PBP', promstavke.vrijed_prst - promstavke.porezi_prst, promstavke.vrijed_prst) ) ), 0) ) pocvrij_sta,
SUM(decode(d.knjiz_dok, '3', 0, '1', 0, decode(d.zal_dok, '+', promstavke.kolic_prst, -promstavke.kolic_prst)) ) trenkol_sta,
SUM(decode(d.knjiz_dok, '3', 0, '0', 0, decode(d.zal_dok, '+', decode(skladista.vrsta_cijene, 'NAB', promstavke.faktcij_prst - NVL(promstavke.rabat_prst, 0) + NVL(promstavke.trosz_prst, 0) + NVL(promstavke.troso_prst, 0), 'PBP', promstavke.vrijed_prst - promstavke.porezi_prst, promstavke.vrijed_prst), -decode(skladista.vrsta_cijene, 'NAB', promstavke.faktcij_prst - NVL(promstavke.rabat_prst, 0) + NVL(promstavke.trosz_prst, 0) + NVL(promstavke.troso_prst, 0), 'PBP', promstavke.vrijed_prst - promstavke.porezi_prst, promstavke.vrijed_prst)) ) ) trenvrij_sta,
stanje.cij_sta cij_sta,
promzag.pgod_prz prz_pgod_prz,
stanje.napomena_sta napomena_sta,
stanje.minzal_sta minzal_sta,
stanje.maxzal_sta maxzal_sta,
stanje.trenikol_sta trenikol_sta,
stanje.trenicij_sta trenicij_sta,
stanje.trenivrij_sta trenivrij_sta,
SUM(decode(d.ul_izl_dok, 'U', decode(d.knjiz_dok, '3', 0, '1', 0, decode(d.zal_dok, '+', promstavke.kolic_prst, -promstavke.kolic_prst)), 0)) kolicina_ulaz,
abs(SUM(decode(d.ul_izl_dok, 'I', decode(d.knjiz_dok, '3', 0, '1', 0, decode(d.zal_dok, '+', promstavke.kolic_prst, -promstavke.kolic_prst)), 0))) kolicina_izlaz,
SUM(decode(d.ul_izl_dok, 'U', decode(d.knjiz_dok, '3', 0, '0', 0, decode(d.zal_dok, '+', promstavke.vrijed_prst, -promstavke.vrijed_prst)), 0)) vrijed_ulaz,
abs(SUM(decode(d.ul_izl_dok, 'I', decode(d.knjiz_dok, '3', 0, '0', 0, decode(d.zal_dok, '+', promstavke.vrijed_prst, -promstavke.vrijed_prst)), 0))) vrijed_izlaz
Я пробовал Regexp::Common
, но это не дало мне именно то, что нужно.
use warnings;
use strict;
use Data::Dumper;
use Regexp::Common;
my $sql = q(
SELECT
promzag.skl_sifra_skl skl_sifra_skl, promstavke.art_sifra_art art_sifra_art,
SUM(decode(d.identifikacija, '17', decode(d.knjiz_dok, '3', 0, '1', 0, decode(d.zal_dok, '+', promstavke.kolic_prst, -promstavke.kolic_prst)), 0)) pockol_sta,
SUM(decode(d.identifikacija, '17', decode(d.knjiz_dok, '3', 0, '0', 0, decode(d.zal_dok, '+', decode(skladista.vrsta_cijene, 'NAB', promstavke.faktcij_prst - NVL(promstavke.rabat_prst, 0) + NVL(promstavke.trosz_prst, 0) + NVL(promstavke.troso_prst, 0), 'PBP', promstavke.vrijed_prst - promstavke.porezi_prst, promstavke.vrijed_prst), -decode(skladista.vrsta_cijene, 'NAB', promstavke.faktcij_prst - NVL(promstavke.rabat_prst, 0) + NVL(promstavke.trosz_prst, 0) + NVL(promstavke.troso_prst, 0), 'PBP', promstavke.vrijed_prst - promstavke.porezi_prst, promstavke.vrijed_prst) ) ), 0) ) pocvrij_sta,
SUM(decode(d.knjiz_dok, '3', 0, '1', 0, decode(d.zal_dok, '+', promstavke.kolic_prst, -promstavke.kolic_prst)) ) trenkol_sta,
SUM(decode(d.knjiz_dok, '3', 0, '0', 0, decode(d.zal_dok, '+', decode(skladista.vrsta_cijene, 'NAB', promstavke.faktcij_prst - NVL(promstavke.rabat_prst, 0) + NVL(promstavke.trosz_prst, 0) + NVL(promstavke.troso_prst, 0), 'PBP', promstavke.vrijed_prst - promstavke.porezi_prst, promstavke.vrijed_prst), -decode(skladista.vrsta_cijene, 'NAB', promstavke.faktcij_prst - NVL(promstavke.rabat_prst, 0) + NVL(promstavke.trosz_prst, 0) + NVL(promstavke.troso_prst, 0), 'PBP', promstavke.vrijed_prst - promstavke.porezi_prst, promstavke.vrijed_prst)) ) ) trenvrij_sta,
stanje.cij_sta cij_sta, promzag.pgod_prz prz_pgod_prz,
stanje.napomena_sta napomena_sta, stanje.minzal_sta minzal_sta,
stanje.maxzal_sta maxzal_sta, stanje.trenikol_sta trenikol_sta,
stanje.trenicij_sta trenicij_sta, stanje.trenivrij_sta trenivrij_sta,
SUM(decode(d.ul_izl_dok, 'U', decode(d.knjiz_dok, '3', 0, '1', 0, decode(d.zal_dok, '+', promstavke.kolic_prst, -promstavke.kolic_prst)), 0)) kolicina_ulaz,
abs(SUM(decode(d.ul_izl_dok, 'I', decode(d.knjiz_dok, '3', 0, '1', 0, decode(d.zal_dok, '+', promstavke.kolic_prst, -promstavke.kolic_prst)), 0))) kolicina_izlaz,
SUM(decode(d.ul_izl_dok, 'U', decode(d.knjiz_dok, '3', 0, '0', 0, decode(d.zal_dok, '+', promstavke.vrijed_prst, -promstavke.vrijed_prst)), 0)) vrijed_ulaz,
abs(SUM(decode(d.ul_izl_dok, 'I', decode(d.knjiz_dok, '3', 0, '0', 0, decode(d.zal_dok, '+', promstavke.vrijed_prst, -promstavke.vrijed_prst)), 0))) vrijed_izlaz
FROM promzag, promstavke, stanje, dokumenti d, skladista WHERE promzag.skl_sifra_skl = promstavke.prz_skl_sifra_skl AND promzag.dok_sifra_dok = promstavke.prz_dok_sifra_dok AND promzag.brdok_prz = promstavke.prz_brdok_prz AND promzag.pgod_prz = promstavke.prz_pgod_prz AND promstavke.prz_skl_sifra_skl = stanje.skl_sifra_skl AND promstavke.art_sifra_art = stanje.art_sifra_art AND promstavke.prz_pgod_prz = stanje.prz_pgod_prz AND promzag.dok_sifra_dok = d.sifra_dok AND promzag.skl_sifra_skl = skladista.sifra_skl GROUP BY promzag.skl_sifra_skl, promstavke.art_sifra_art, stanje.pockol_sta, stanje.pocvrij_sta, stanje.cij_sta, promzag.pgod_prz, stanje.napomena_sta, stanje.minzal_sta, stanje.maxzal_sta, stanje.trenikol_sta, stanje.trenicij_sta, stanje.trenivrij_sta
);
my @all_parts = split /$RE{balanced}{-parens=>'()'}/x, $sql;
for (@all_parts) {
y|\n\r| |d;
print "$_\n\n";
}
Ответ или решение
Анализ SQL-запроса: парсинг выбранных колонок
В современном программировании часто возникает необходимость эффективно анализировать SQL-запросы, особенно в сложных системах, где используются агрегатные функции и многоуровневые операции. В данной статье мы рассмотрим подход к парсингу столбцов из указанного SQL-запроса. Этот процесс включает в себя различные аспекты, от базовых SQL-принципов до использования регулярных выражений для автоматизации анализа.
Проблема и её содержание
У нас есть SQL-запрос, который выбирает столбцы из нескольких таблиц и включает в себя агрегации и сложные условия. Нам необходимо извлечь отдельные столбцы из этого запроса и представить их в массиве. SQL-запрос может выглядеть следующим образом:
SELECT
promzag.skl_sifra_skl skl_sifra_skl,
promstavke.art_sifra_art art_sifra_art,
SUM(decode(d.identifikacija, '17', decode(d.knjiz_dok, '3', ...))) pockol_sta,
...
FROM tablex
Как видно, некоторые строки представляют собой агрегатные функции (SUM
, COUNT
и другие), а некоторые используются для выбора отдельных столбцов, таких как promzag.skl_sifra_skl
.
Алгоритм парсинга
Для успешного выполнения задачи парсинга следует придерживаться структурированного подхода. Вот шаги, которые мы можем выполнить:
-
Определение структуры запроса: Мы сосредоточимся на секции
SELECT
, игнорируяFROM
иWHERE
. -
Использование регулярных выражений: Это инструмент, который поможет выделить каждую отдельную колонку из запроса. Пример регулярного выражения для этого может выглядеть так:
my $regex = qr/(?:\s*,\s*|^)\s*([^,]+?)\s+(\w+)\s*(?=,|$)/;
Это выражение выделит все столбцы вместе с их алиасами.
-
Выполнение парсинга и сбор результата: Мы проходим по строке с запросом и извлекаем все соответствия, сохраняя их в массив.
Пример кода на Perl
Ниже представлен пример кода на Perl, который выполняет описанные выше шаги:
use strict;
use warnings;
my $sql = q(
SELECT
promzag.skl_sifra_skl skl_sifra_skl,
promstavke.art_sifra_art art_sifra_art,
SUM(decode(d.identifikacija, '17', ...)) pockol_sta,
...
FROM tablex
);
# Регулярное выражение для извлечения колонок
my @columns;
while ($sql =~ /(\s*,\s*|^)\s*([^,]+?)\s+(\w+)\s*(?=,|\s+FROM|$)/g) {
push @columns, $2; # Добавляем имя колонки в массив
}
# Вывод результатов
foreach my $column (@columns) {
print "$column\n";
}
Разбор результата
Этот код извлечет все столбцы, определенные в секции SELECT
, и сохранит их в массиве. В результате вы получите массив, содержащий:
promzag.skl_sifra_skl
promstavke.art_sifra_art
SUM(decode(d.identifikacija, '17', ...)) pockol_sta
- и другие…
Заключение
Парсинг SQL-запросов является важной задачей в области обработки данных. Используя регулярные выражения и подходы, аналогичные приведенному выше, мы можем эффективно извлекать необходимые компоненты из запросов. Это открывает множество возможностей для анализа, модификации и оптимизации SQL-запросов в различных системах.
Регулярное применение подобных техник улучшает качество кода и облегчает сопровождение проектов, что делает вас более эффективным IT-специалистом.