14 / 14 / 0
Регистрация: 24.09.2015
Сообщений: 208
1

Составление (генерация) сложных SQL запросов к Access

16.06.2019, 13:03. Показов 1425. Ответов 15

Author24 — интернет-сервис помощи студентам
День добрый, уважаемые участники форума!
Требуется консультация по вопросу как правильно организовать группу запросов из VВ.Nеt к Access и помощь в реализации данной задумки.
Есть форма с комбобоксами которые при запуске содержат в себе основные списки данных из подключенной БД. Далее при выборе значения из любого комбобокса у нас должны подгрузиться только те значения которые имеют отношение к выбранному значению в комбобоксе.
С этим сложностей вроде нет.
Основная сложность заключается в том, чтобы выполнялась фильтрация не по одному значению из комбобокса а с учётом всех комбобоксов в которых уже произведен выбор значений.
Можно прописать на каждую выборку отдельный запрос и получится километровая портянка(частично уже начал так делать), а можно написать код который будет собирать запрос проверив наличие значений в комбобоксах и на основании этих данных составлять запрос.
В принципе если получится создать нечто подобное, то в дальнейшем можно написать отдельную библиотеку)

Прилагаю файлы проекта вместе с БД.
Вложения
Тип файла: rar WindowsApplication13.rar (421.6 Кб, 7 просмотров)
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
16.06.2019, 13:03
Ответы с готовыми решениями:

Составление сложных SQL запросов к Access из VB.Net
Всем доброго времени суток! Не так давно начал создавать базу данных в Access и создание формы для...

Несколько задач на составление сложных запросов
Господа программисты! Помогите пожалуйста решить задачи по бд надо с помощью сложных запросов...

Генератор (сложных) SQL-запросов
Привет! Есть приложение, которое получает данные из базы. Вариантов запросов много, запросы...

Разработка сложных и коррелированных SQL-запросов
Вывести все сведения о продавцах, которые имеют покупателей, сделавших за 2001 год более 5...

15
6217 / 2465 / 725
Регистрация: 11.04.2015
Сообщений: 3,985
Записей в блоге: 43
17.06.2019, 12:43 2
Евгений_Пермь, а как именно влияют на запрос комбобоксы? Допустим, если это речь о фильтрации по определенному полю, которое задано для каждого комбобокса, то, по всей видимости, на запросе это будет отражаться дополнительным AND в кляузе WHERE. Ну если так, то можно сопоставить каждому комбобоксу то поле по которому он фильтрует (это можно сделать в свойстве Tag или словарик составить) и дальше проходишься в цикле по всем таким комбобоксам и если в нем выбрано значение, то добавляешь в текст " AND " & [имя поля соответствующее комбобоксу] & " = " & [Имя комбобокса].Value. Потом полученную строку добавить к WHERE и дело в шляпе. Если случай более сложный, то надо его описать подробнее.
1
14 / 14 / 0
Регистрация: 24.09.2015
Сообщений: 208
17.06.2019, 13:23  [ТС] 3
Цитата Сообщение от diadiavova Посмотреть сообщение
Евгений_Пермь, а как именно влияют на запрос комбобоксы? Допустим, если это речь о фильтрации по определенному полю, которое задано для каждого комбобокса, то, по всей видимости, на запросе это будет отражаться дополнительным AND в кляузе WHERE. Ну если так, то можно сопоставить каждому комбобоксу то поле по которому он фильтрует (это можно сделать в свойстве Tag или словарик составить) и дальше проходишься в цикле по всем таким комбобоксам и если в нем выбрано значение, то добавляешь в текст " AND " & [имя поля соответствующее комбобоксу] & " = " & [Имя комбобокса].Value. Потом полученную строку добавить к WHERE и дело в шляпе. Если случай более сложный, то надо его описать подробнее.
Тут еще нужно использовать INNER JOIN
Т.е. если откроете исходник, то там в общем модуле написаны 4 запроса, которые как раз и связаны с комбобоксами.
Чуть позже смогу привести примеры для остальных комбобоксов.
А так мысль верная)
0
14 / 14 / 0
Регистрация: 24.09.2015
Сообщений: 208
17.06.2019, 20:46  [ТС] 4
Вот такой вот запрос к примеру сформировать...

SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
SELECT
  Производители_станков.[Производитель станка],
  Типы_станков.[Тип станка],
  Модели_станков.[Модель станка],
  Производители_ЧПУ.[Производитель ЧПУ],
  Модели_ЧПУ.[Модель ЧПУ],
  Станки.Транзакция,
  Станки.[Серийный номер],
  Города.Город,
  Организации.Организация,
  Станки.Комментарий,
  Документы.[Имя документа],
  Бэкапы.[Имя бэкапа]
FROM ((Города
INNER JOIN (Типы_станков
INNER JOIN (Производители_станков
INNER JOIN (Модели_станков
INNER JOIN (Производители_ЧПУ
INNER JOIN (Модели_ЧПУ
INNER JOIN (Организации
INNER JOIN Станки
  ON Организации.[Код организации] = Станки.[Код организации])
  ON Модели_ЧПУ.[Код модели ЧПУ] = Станки.[Код модели ЧПУ])
  ON Производители_ЧПУ.[Код производителя ЧПУ] = Модели_ЧПУ.[Код производителя ЧПУ])
  ON Модели_станков.[Код модели станка] = Станки.[Код модели станка])
  ON Производители_станков.[Код производителя] = Модели_станков.[Код производителя])
  ON Типы_станков.[Код типа станка] = Модели_станков.[Код типа станка])
  ON Города.[Код города] = Организации.[Код города])
INNER JOIN Документы
  ON (Типы_станков.[Код типа станка] = Документы.[Код типа станка])
  AND (Станки.[Код станка] = Документы.[Код станка])
  AND (Производители_ЧПУ.[Код производителя ЧПУ] = Документы.[Код производителя ЧПУ])
  AND (Производители_станков.[Код производителя] = Документы.[Код производителя])
  AND (Модели_ЧПУ.[Код модели ЧПУ] = Документы.[Код модели ЧПУ])
  AND (Модели_станков.[Код модели станка] = Документы.[Код модели станка]))
INNER JOIN Бэкапы
  ON Станки.[Код станка] = Бэкапы.[Код станка]
WHERE (((Производители_станков.[Производитель станка]) = "первый"));
Вот так я примерно представляю себе данное упрощение, но пока сомневаюсь в этом...

VB.NET
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Public Class [Function]
    ''' <summary>
    ''' SELECT
    ''' </summary>
    ''' <param name="PrevStr">Строка содержащая запрос SELECT</param>
    ''' <param name="N_Table">Имя таблицы</param>
    ''' <param name="N_Field">Имя поля</param>
    ''' <returns>Возвращает функцию SELECT для строки запроса</returns>
    Public Function FSelect(PrevStr As String, N_Table As String, N_Field As String) As String
        If PrevStr = "" Then
            Return "SELECT " & N_Table & ".[" & N_Field & "]"
        Else
            Return PrevStr & ", " & N_Table & ".[" & N_Field & "]"
        End If
    End Function
    ''' <summary>
    ''' INNER JOIN
    ''' </summary>
    ''' <param name="PrevStr">Строка содержащая запрос INNER JOIN</param>
    ''' <param name="N_T1">имя первой табицы</param>
    ''' <param name="N_T2">Имя второй таблицы</param>
    ''' <param name="Field">Имя поля</param>
    ''' <returns>Возвращает функцию INNER JOIN для строки запроса</returns>
    Public Function FInnJ(PrevStr As String, N_T1 As String, N_T2 As String, Field As String)
        If PrevStr = "" Then
            Return N_T1 & " INNER JOIN " & N_T2 & "ON" & N_T1 & ".[" & Field & "]=" & N_T2 & ".[" & Field & "]"
        Else
            Return N_T1 & " INNER JOIN " & "(" & PrevStr & ")ON" & N_T1 & ".[" & Field & "]=" & N_T2 & ".[" & Field & "]"
        End If
    End Function
End Class
Добавлено через 1 час 15 минут
diadiavova, при первом запуске или когда все комбобоксы "пустые", у нас грузятся все данные в списки. Дальше например выбрали мы "Производителя станка", все остальные поля должны обновиться в соответствии со связями с данным производителем. Дальше например выбрали "Город" и о5-же у нас остальные комбобоксы должны обновить данные в соответствии с производителем и городом и т.д...
Если на каждое условие прописывать отдельный запрос, то получится довольно ГРОМОЗДКА и плохо читаемая и редактируемая портянка...
Как я это примерно вижу, нужно описать "все" SQL функции, которые будут использоваться, дальше из этих функций написать метод который будет собирать запрос и дальше уже отправлять его к Access.
0
6217 / 2465 / 725
Регистрация: 11.04.2015
Сообщений: 3,985
Записей в блоге: 43
18.06.2019, 01:16 5
Евгений_Пермь, я смотрел проект, но из проекта, равно как и из приведенного здесь кода, достаточно сложно понять как должен меняться код запроса, в зависимости от выбора того или иного комбобокса.
По генерации текста могу дать пару советов. Во-первых, если у тебя версия языка не очень старая, то с некоторых пор бейсик поддерживаетИнтерполированные строки, формировать текст с ними намного легче. Если же требуется более сложный вариант, то обрати внимание на вот такую штуку Создание кода и текстовые шаблоны T4 - Visual Studio | Microsoft Docs, особое внимание обрати на это Создание текста во время выполнения с помощью текстовых шаблонов T4 - Visual Studio | Microsoft Docs. Лучше использовать с расширением студии, например таким T4 Editor - VS add-in for editing T4 templates | Devart, или поищи в расширениях студии, там есть еще пара вариантов.
В общем и целом, вставишь в шаблон полный текст запроса, а те элементы, которые зависят от комбобоксов обернешь условиями и вставишь значения. В шаблон можно передавать аргументы, так что там есть возможность достаточно тонкой настройки генерации текста.
1
14 / 14 / 0
Регистрация: 24.09.2015
Сообщений: 208
18.06.2019, 21:34  [ТС] 6
diadiavova, попробую еще раз описать нужный алгоритм работы)
Имеем производителей станков с различным модельным рядом.
Модели подразделяются на типы, т.е. "Тип1" "Тип2" и т.д...

Дальше нам нужно узнать в каких городах находятся станки производителя №1.
Выбрали производителя №1, в списке "города" сформировался список городов отфильтрованный по производителю №1.
Теперь мы хотим посмотреть какие именно модели производителя №1 находятся в городе Омске.
Выбрали "Омск" и в спике моделей должен сформироваться список моделей производителя №1 которые находятся в Омске.

Или например в обратном порядке: выбрали город - получили список производителей, выбрали производителя - получили список моделей выбранного производителя в данном городе.
И так со всеми списками, модели, города, организации, производители ЧПУ, модели ЧПУ, серийные номера...

Получается взаимо-исключающая выборка...
0
258 / 199 / 49
Регистрация: 18.12.2015
Сообщений: 416
18.06.2019, 22:01 7
Евгений_Пермь, а есть смысл писать такие "полотна" и каждый раз дергать базу?
Может загнать один раз в DataTable всю таблицу общим запросом и потом ее фильтровать по нужным вам условиям?
Вот недавняя тема.
Если конечно у вас там данных не мильоны строк.
1
14 / 14 / 0
Регистрация: 24.09.2015
Сообщений: 208
18.06.2019, 22:12  [ТС] 8
Jungl, не миллионы конечно, но десятки тысяч точно могут быть...
Не плохая идея, попробую развить данное направление.
По сути что-так, что-так мы грузим данные из базы в оперативку.
Просто планируется еще делать поиск по частичному вводу данных в комбобокс, но это уже другая тема)
0
6217 / 2465 / 725
Регистрация: 11.04.2015
Сообщений: 3,985
Записей в блоге: 43
19.06.2019, 07:42 9
Евгений_Пермь, то есть иными словами код запроса зависит не только от выбора в комбобоксах, но и от того, в каком порядке был сделан этот выбор? Да еще и при выборе в одном комбобоксе содержимое остальных меняется? А как быть, если пользователь вдруг решит изменить выбор в одном из комбобоксов, где он уже раньше что-то выбрал? Ну или вообще как предусмотреть незапланированное поведение пользователя? Мне что-то думается, что в данной ситуации надо действовать как-то иначе. Например сделать что-то типа визарда, где каждое новое окошко будет содержать только те варианты, которые зависят от ранее сделанного выбора и т. п. Тогда и промежуточные запросы будет формировать проще.
1
1135 / 876 / 152
Регистрация: 25.07.2015
Сообщений: 1,954
19.06.2019, 08:21 10
Цитата Сообщение от Jungl Посмотреть сообщение
Может загнать один раз в DataTable всю таблицу общим запросом
Не самая лучшая идея.
Цитата Сообщение от Евгений_Пермь Посмотреть сообщение
По сути что-так, что-так мы грузим данные из базы в оперативку
Отнюдь.
Ваш запрос выгружает в ОП отфильтрованные данные , т.е. некий укороченный набор,
Jungl же по сути предлагает слить все таблицы , участвующие в запросе.
Не далеко налететь на исключение "Out of Memory" . Причём количество записей не столь важно :
можно разместить в память миллионы записей типа boolean без рисков переполнения и без потери
производительности , а можно тысячью-другой записей типа Text (я уж молчу про Memo) уложить память в аут.
(Все приведённые данные от access, вы же его используете как хранилище.)
Плюс механизмы реализации выборки (запросы) бывают очень энергоёмкие без оптимизации.
У меня были случаи , когда при копировании 5-7 тыс. строк из access 8-гиговый ноут отваливался в
недостаток памяти.

Воспользуйтесь лучше советом diadiavova и пересмотрите саму концепцию.
1
14 / 14 / 0
Регистрация: 24.09.2015
Сообщений: 208
19.06.2019, 08:40  [ТС] 11
diadiavova, на случай если пользователь захочет изменить уже отфильтрованный комбобокс, потребуется сделать сброс запросов. Т.е. нажать на кнопку например "сброс" и данные в списках комбобоксов должны вернуться к исходному варианту как при загрузке формы. Я так это вижу, вчера тоже про это подумал.
А если прописывать каждый запрос по отдельности без автоматизации составления запроса, то получается порядка 100 отдельных вариантов запросов, а тут и запутаться не долго да и в случае редактирования будет куча проблем.
Думал еще о возможности в условиях для составления запросов указать связи полей которые имеются в БД, но пока не продумал как это можно задействовать.
0
1135 / 876 / 152
Регистрация: 25.07.2015
Сообщений: 1,954
19.06.2019, 11:18 12
Цитата Сообщение от Евгений_Пермь Посмотреть сообщение
Т.е. нажать на кнопку например "сброс" и данные в списках комбобоксов должны вернуться к исходному варианту как при загрузке формы
К сожалению, Евгений, почти всегда вИдение разработчика в плане функционала и тем более последовательности
действий и конечного юзера практически всегда не одно и то же.
diadiavova, предложил вам найти некое соломоново решение , чтобы и юзеру было максимально удобно,
и ваша прога не падала каждый раз , когда юзер что-то жмакнул не то )))
Не зря же существует присказка, возведённая практически в степень истины :
" Любую инструкцию по применению надо начинать словами : " ну что, дурачок, уже сломал ?"
3
14 / 14 / 0
Регистрация: 24.09.2015
Сообщений: 208
19.06.2019, 12:04  [ТС] 13
Kulma, тут по сути не то и не жамкнешь, данные в списках из бд, если и будут выборки по части слова, то можно состряпать проверку на возврат пустого результата запроса и выдачу предупреждения, в крайнем случае нажал на сброс и данные в первоначальном виде во всех комбобоксах.
А так полностью согласен, но думаю тут будет достаточно кнопки "отмена/сброс".
0
1135 / 876 / 152
Регистрация: 25.07.2015
Сообщений: 1,954
19.06.2019, 12:33 14
Цитата Сообщение от Евгений_Пермь Посмотреть сообщение
в крайнем случае нажал на сброс и данные в первоначальном виде во всех комбобоксах.

Не по теме:

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

1
6217 / 2465 / 725
Регистрация: 11.04.2015
Сообщений: 3,985
Записей в блоге: 43
19.06.2019, 12:54 15
Цитата Сообщение от Евгений_Пермь Посмотреть сообщение
А если прописывать каждый запрос по отдельности без автоматизации составления запроса
А я об этом и не говорю, мало того подбросил идей о том, как это реализовать. Ну просто давай возьмем, например, запрос для заполнения одного комбобокса и для всех сразу. Просто сравни их и все увидишь сам. Для заполнения одного комбобокса потребуется одно поле в селекте, фильтры в вэа и никаких иннерджоинов. Допустим, ты не хочешь сильно усложнять интерфейс, тогда можно формировать список каждого комбобокса в обработчике события DropDown и заполнять только его, а не все сразу. Просто чтобы не вызывать конфликтов. Кроме того, в том же обработчике желательно заморозить все комбобоксы, в которых значение уже выбрано, иначе, если пользователь снова туда полезет, то весь процесс будет сбит. Ну хотя бы так.
2
14 / 14 / 0
Регистрация: 24.09.2015
Сообщений: 208
19.06.2019, 18:02  [ТС] 16
Kulma,

Не по теме:

Сталкивался я с подобным, когда умудрялись впихнуть невпихуемое, казалось бы, ну вот в этом месте уже всё предусмотрел от ошибок, ан нет оказывается не всё и на вопрос зачем это сделали, как правило не следует внятных ответов.)))

0
19.06.2019, 18:02
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
19.06.2019, 18:02
Помогаю со студенческими работами здесь

Составление запросов SQL
Ребят,выручайте. Изучаю язык SQL, дали задание написать запросы Представьте 2 таблицы:...

Динамическое создание запросов в MS Access как в MS SQL
Доброго времени суток! Пишу программу на Delphi. Обращение к разным базам. С MS SQL все...

Вывод данных в БД Access 2003 при использование SQL запросов. Delphi
Добрый день или вечер Камрады, столкнулся с проблемой при использование структуры &quot;insert into&quot;,...

Создание баз и таблиц в Access при помощи SQL-запросов типа DDL
Господа, не пытайтесь создавать базы и таблицы в Access при помощи SQL-запросов типа DDL....


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru