powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / Microsoft Access [игнор отключен] [закрыт для гостей] / Запрос на выборку. Как упростить?
25 сообщений из 26, страница 1 из 2
Запрос на выборку. Как упростить?
    #39740656
Siompc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здравствуйте люди :) Подскажите в таком вопросе. Значит суть такая. Есть таблицы товары и категории в базе access. В товарах есть различные параметры. В категориях только код товара и категории к которым он принадлежит. Один товар обычно в нескольких категориях состоит. Необходимо сделать такую выборку, которая будет отображать например 20 товаров на n странице с нужными параметрами и в выбранной категории. Например если страница первая - то первые 20 товаров, удовлетворяющие поиску. Если страница вторая, то уже 20 товаров после тех, которые на первой странице.
Каким образом это реализовано у меня на данный момент. А очень плохо. У меня категории находятся в таблице товаров в виде строки. И я использую оператор LIKE для поиска совпадений в этой строке. А запрос на выборку следующий:


SELECT * FROM (SELECT TOP 20 * FROM (SELECT TOP 40 * FROM `Товары` WHERE `Наличие`=true AND `Цена`>=70 AND `Категория` LIKE '%Металл%' ORDER BY `Дата добавления` DESC) ORDER BY `Дата добавления` ASC) ORDER BY `Дата добавления` DESC;

По сути три запроса. Последний только для сортировки по убыванию. Но я пробую выполнить запрос на получение количества товаров в нужной категории

SELECT COUNT(*) FROM `Товары` WHERE `Наличие`=true AND `Цена`>=70 AND `Категория` LIKE '%Металл%'

И получаю значение через 250мс. При это у меня всего лишь 50.000 записей. Страшно представить что будет при миллионе, когда будут идти запросы сразу от многих клиентов.
В связи с этим вопрос. Как ускорить работу запроса?
Понятное дело надо выносить категории в отдельную таблицу. Добавить в запросе вторую таблицу и в выборке сделать т1.категория=металл and т1.кодтовара=т2.код. Кажется так. Но тогда база будет для каждой строки категорий делать запрос на сравнение всех кодов в первой таблице? Не получится шило на мыло? И есть ли какой-то способ постраничной выборки быстрее, чем используются мной?

Модератор: Тема перенесена из форума "MySQL".
...
Рейтинг: 0 / 0
Запрос на выборку. Как упростить?
    #39740777
Озверин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Siompc,

1. По скорости - нормализация вас спасет.
Справочник: ТаблицаTоваров: КодТовара(PrimaryKey), ИмяТовара
Справочник: ТаблицаКатегорий: КодКатегории(PrimaryKey), ИмяКатегории
Кросс данные: КатегорияТовар: КодКатегории, КодТовара(UniqueKey по 2м полям)

Соответственно выборка превращается в

Код: vbnet
1.
2.
3.
SELECT g.КодТовара, g.ИмяТовара
FROM ТаблицаTоваров g INNER JOIN КатегорияТовар с ON g.КодТовара = c.КодТовара
WHERE c.КодКатегории = 1



Либо с группировкой, если выборка из нескольких категорий:

Код: vbnet
1.
2.
3.
4.
SELECT g.КодТовара, g.ИмяТовара
FROM ТаблицаTоваров g INNER JOIN КатегорияТовар с ON g.КодТовара = c.КодТовара
WHERE c.КодКатегории IN (1,2)
GROUP BY g.КодТовара, g.ИмяТовара



2. Т.к. в Ms Access нет никаких лимитов , то выборка диапазона превращется в запрос вида:

Код: vbnet
1.
WHERE КодТовара BETWEEN  1 AND 100 


(синтаксис between я уже не помню)
...
Рейтинг: 0 / 0
Запрос на выборку. Как упростить?
    #39740827
Фотография sdku
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Siompc,
Я балдею от таких вопросов.
Ни малейших сомнений в правильности схемы БД.(только глубокая уверенность в том,что всё верно. По личному опыту знаю что на одной структуре выворачиваешься наизнанку,но сделать так,как хочется,не получается-стоит изменить структуру и все элементарно решается)
Как это может быть-один товар в нескольких категориях? Может стоит подумать о разбивке на категории и внутри них на подкатегории. Страницы в запросе-это что-то новое(может Вы говорите об отчете. Запрос и отчет,в котором возможна группировка и внедрение подчиненных отчетов, это таки разные вещи)
...
Рейтинг: 0 / 0
Запрос на выборку. Как упростить?
    #39740945
Siompc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
sdku,
Я балдею от таких ответов.
1- Например категории материала из которого сделан товар. Может быть в нескольких категориях?
2- Я имею ввиду постраничную выборку. Никаких отчетов. Я работаю с базой через сторонние программы на платформе .net
3- Где я писал, что я не сомневаюсь в правильности схемы БД?

Озверин,
Большое спасибо за ответ.
Сперва за выборку диапазона с BETWEEN. Я не могу так сделать. Потому что мне в итоге должно вывести ровно 20 записей товаров. Некоторые товары могут быть недоступны. например отсутствовать. И если выбирать между 1 AND 20, то при отсутствующем товаре или при несоответствии условию отбора результат будет меньше 20 записей. А может и вовсе 0. Поэтому я использовал такой запрос, который ищет все записи по условию с ограничением 40, потом переворачивает их и отсекает 20. Это получается отображение товаров второй страницы в количестве 20 штук. Третья страница - TOP 60 и потом результаты переворачиваются и отсекается 40...

Если я правильно понял - необходимо три таблицы. 1 с именем товара, 2 с именем категории, 3 с кодом товара и кодом категории. Такой принцип я использовал в тегах к этим товарам. добавил таблицу наименований тегов, и таблицу с кодами тегов и кодами товаров. Но вот запрос, который выбирает как раз эти самые 20 записей, для поиска по тегам, намного сложнее и, как мне кажется, дольше. Потому что помимо сравнения одного или нескольких тегов, к которым принадлежит материал, нужно получить данные материала, в которых можно проверить есть ли он на складе и другие параметры выборки, да и еще отобрать опять же нужное количество для страницы. Те самые 20 штук... Все сложно. Вот запрос мой поиска по тегам, если так-же будут работать категории, тогда он будет таким же?

Сперва я получаю номера тегов по их названию
SELECT `Код` FROM `Теги наименования` WHERE `Тег`='Имя1' OR `Тег`='Имя2'

Потом я составляю сложный запрос
SELECT DISTINCT t1.* FROM ТегиТовары as t1, ТегиТовары as t2 WHERE t1.ТегКод = 8 AND t2.ТегКод = 9 AND t1.ТоварКод = t2.ТоварКод

Чем больше одновременно мы ищем наименований тегов, принадлежащих к одному товару, тем больше в запросе будет добавляться таблиц для сравнения принадлежности к коду одного товара (as t1,t2,t3...)

и только после этого (!!!) когда мы получили список всех кодов материала (а их нужно получить именно все, т.к. их нужно будет проверить на наличие и другие параметры выборки, что бы получить 20 штук на странице)
мы подаем третий запрос. Который по сути такой-же, как я писал выше. Ищем товары по полученным кодам, в таблице с товарами смотрим, что бы эти товары были на складе + другие параметры выборки. Получаем TOP n*20, потом переворачиваем и отрезаем
n*20-20.

Что я делаю не так? Как мне выкрутиться с этого положения?
...
Рейтинг: 0 / 0
Запрос на выборку. Как упростить?
    #39740949
Прогер_самоучка
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SiompcЧто я делаю не так?для начала начните использовать тэги на форуме.
...
Рейтинг: 0 / 0
Запрос на выборку. Как упростить?
    #39740958
Siompc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Прогер_самоучка,
Я пришел сюда за помощью. Вам так тоже отвечают, когда вы обращаетесь к специалистам?

- У меня не включается компьютер!
- Для начала почитайте книгу "Ремонт компьютеров"
...
Рейтинг: 0 / 0
Запрос на выборку. Как упростить?
    #39740977
Прогер_самоучка
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SiompcПрогер_самоучка,
Я пришел сюда за помощью. Вам так тоже отвечают, когда вы обращаетесь к специалистам?

- У меня не включается компьютер!
- Для начала почитайте книгу "Ремонт компьютеров"у вас «наклепано» почти 200 сообщений, за это время вы были просто обязаны научиться пользоваться тэгом SRC(находится на панели чуть выше тела сообщения), дабы упростить жизнь людям, которые хотят вам помочь.
З.Ы. И аналогия ваша кривая
...
Рейтинг: 0 / 0
Запрос на выборку. Как упростить?
    #39740988
Фотография sdku
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Siompcsdku,
Я балдею от таких ответов.
1- Например категории материала из которого сделан товар. Может быть в нескольких категориях?Тогда в базе должна быть ветвь "производство", где один и тот же материал используется при производстве разных товаров (работа с готовым товаром-пофиг из ЧЕГО он сделан и различные вопросы про из ЧЕГО он сделан это таки не одно и то же)
Мухи и котлеты должны быть разделены
...
Рейтинг: 0 / 0
Запрос на выборку. Как упростить?
    #39741024
Siompc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Прогер_самоучка,
С телефона добавлял ответы? Уж извините, если вам трудно прочитать одну строку кода без тега. Лучше чем засорять сообщениями топ, помогли бы с решением проблемы
...
Рейтинг: 0 / 0
Запрос на выборку. Как упростить?
    #39741030
Siompc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
sdku,
Вы читали суть проблемы? Добавление еще одной таблицы с разделением категорий я описал вторым ответом по аналогии с тегами. Запрос усложняется, время на обработку так-же значительно увеличивается. Может вы поможете с составлением правильного запроса?
...
Рейтинг: 0 / 0
Запрос на выборку. Как упростить?
    #39741038
Фотография __Michelle
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SiompcПотом я составляю сложный запрос
Код: sql
1.
2.
SELECT DISTINCT t1.* FROM ТегиТовары as t1, ТегиТовары as t2 
WHERE t1.ТегКод = 8 AND t2.ТегКод = 9 AND t1.ТоварКод = t2.ТоварКод

Может, так сделать?
Код: sql
1.
2.
3.
SELECT DISTINCT t1.* 
FROM ТегиТовары as t1 INNER JOIN ТегиТовары as t2 ON t1.ТоварКод = t2.ТоварКод
WHERE t1.ТегКод = 8 AND t2.ТегКод = 9
...
Рейтинг: 0 / 0
Запрос на выборку. Как упростить?
    #39741048
Siompc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
__Michelle,
А получится 2 раза указать INNER JOIN, если, например, будут искать сразу по трем тегам? Тогда мой запрос станет таким:
Код: sql
1.
2.
3.
4.
SELECT DISTINCT t1.* 
FROM ТегиТовары as t1, ТегиТовары as t2, ТегиТовары as t3 
WHERE t1.ТегКод = 2 AND t2.ТегКод = 7 
AND t3.ТегКод = 8 AND t1.ТоварКод = t2.ТоварКод AND t2.ТоварКод = t3.ТоварКод 
...
Рейтинг: 0 / 0
Запрос на выборку. Как упростить?
    #39741059
Фотография mds_world
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: sql
1.
2.
3.
4.
5.
SELECT DISTINCT t1.* 
FROM ТегиТовары as t1,  ТегиТовары as t2, ТегиТовары as t3,
t1 INNER JOIN t2 ON t1.ТоварКод = t2.ТоварКод,
t2 INNER JOIN t3 ON t2.ТоварКод = t3.ТоварКод
WHERE t1.ТегКод = 2 AND t2.ТегКод = 7 AND t3.ТегКод = 8
...
Рейтинг: 0 / 0
Запрос на выборку. Как упростить?
    #39741084
Озверин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Siompc,


0. Если нужна выборка без пробелов, то можно ориентироваться не на код товара, а на номер записи. Для того, чтобы каждую запись запроса пронумеровать есть несколько хитростей. Где-то в FAQ на форуме было что-то про запрос DIGITS, но я бы написал примитвную встроенную ф-ию и пронумеровал ей.

Тогда запрос бы превратился в:

Код: vbnet
1.
WHERE НомерЗаписи BETWEEN  1 AND 20



2. Постраничную выборку было удобно сделать по заранее открытому рекордсету(упорядоченному по коду или имени товара, предположим). Учитывая, что вы заранее можете рассчитать, на каком номере записи вы будете начинать каждую новую страницу, вы можете легко перемещаться в нужную позицию рекодсета и вычитывать нужно кол-во записей.

3.Я не понял логики выбора тегов, если честно.

Тут - все понятно.
Код: vbnet
1.
SELECT `Код` FROM `Теги наименования` WHERE `Тег`='Имя1' OR `Тег`='Имя2'



А тут - уже нет.
Код: vbnet
1.
SELECT DISTINCT t1.* FROM ТегиТовары as t1, ТегиТовары as t2 WHERE t1.ТегКод = 8 AND t2.ТегКод = 9 AND t1.ТоварКод = t2.ТоварКод



Я не понял, что этот запрос делает, я думаю, что ваши 2 запроса можно заменить следующим:

Код: vbnet
1.
2.
3.
SELECT DISTINCT  tt.ТоварКод
FROM ТегиТовары tt INNER JOIN `Теги наименования` ti ON tt.ТегКод = ti.Код
WHERE tt.Тег IN('Имя1','Имя2')
...
Рейтинг: 0 / 0
Запрос на выборку. Как упростить?
    #39741087
Озверин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Озверин,
Код: vbnet
1.
2.
3.
SELECT DISTINCT  tt.ТоварКод
FROM ТегиТовары tt INNER JOIN `Теги наименования` ti ON tt.ТегКод = ti.Код
WHERE ti .Тег IN('Имя1','Имя2')
...
Рейтинг: 0 / 0
Запрос на выборку. Как упростить?
    #39741117
Надеюсь, ваши "сторонние программы" умеют работать с Recordset-ми?
И таблица (запрос?) "Товары" имеет ключевое поле (ID)?
Я бы открыл Recordset на "третьем запросе" - перешел на 21-ю запись - в цикле пробежал по 20-и записям и собрал ID в строку ч-з запятую, а затем запрос из "Товары" с единственным условием [ID] In (1,3,...). Для другой порции - аналогичные действия та том же Recordset-е.
...
Рейтинг: 0 / 0
Запрос на выборку. Как упростить?
    #39741119
Siompc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
mds_world,
Хорошо.) Спасибо. Переделаю программу для подачи таких запросов.


но проблема основная остается )

Еще немного рассуждений.
Допустим я сделал категории в отдельной таблице как теги.
Есть такие таблицы, для примера:
1-Товар [Код, Наименование, Описание, Наличие, Цена, Дата добавления]
2-Материал [Код, Наименование]
3-МатериалТовар [КодМатериал, КодТовар]

У меня есть программа, в которой пользователь ищет товары по критериям. Например:
Цена <50, Наличие =true, Материал =Пластик,Дерево,Металл

Он задал эти критерии и нажал на 2 страницу поиска. Ему должно отобразится 20 разных наименований товара, которые прошли отбор. Либо меньше 20, если это последняя страница и всего по условиям отбора мы получили 35 наименований.

Как я сейчас действую. Программа сперва делает 1 запрос на получение кодов материала
Код: sql
1.
SELECT `Код` FROM `Материал` WHERE `Тег`='Пластик' OR `Тег`='Дерево'  OR `Тег`='Металл'


Все результаты сохраняет в массив.
Например были получены коды материалов 1,2,3. Далее программа делает второй запрос на получение кодов товара:
Код: sql
1.
2.
3.
4.
5.
SELECT DISTINCT t1.* 
FROM МатериалТовар as t1,  МатериалТовар as t2, МатериалТовар as t3,
t1 INNER JOIN t2 ON t1.КодТовар= t2.КодТовар,
t2 INNER JOIN t3 ON t2.КодТовар= t3.КодТовар
WHERE t1.КодМатериал = 1 AND t2.КодМатериал= 2 AND t3.КодМатериал= 3


Все коды материалов опять сохраняются в переменную массива. (Знаю это ОЧЕНЬ плохо. Так как если будет найдено 500.000 материалов, придется все их коды сохранять и потом присвистывать материалы по этим кодам)
Третий и последний запрос. Нужно отобразить 20 товаров 2 страницы.
Код: sql
1.
SELECT * FROM (SELECT TOP 20 * FROM (SELECT TOP 40 * FROM `Товар` WHERE `Наличие`=true AND `Цена`<50 AND `Код` IN (" & Тут перечисление кодов материала & ") ORDER BY `Дата добавления` DESC) ORDER BY `Дата добавления` ASC) ORDER BY `Дата добавления` DESC;


Вот. Вся суть - это очень долго и плохо. Можно было бы как-то объединить все три запроса в один, тогда не пришлось бы сохранять в переменные все идентификаторы. Это чуть бы ускорило работу. И проверить насколько быстро будут выдаваться результаты. Это реально сделать? Не будет ошибки, что запрос слишком сложный?
...
Рейтинг: 0 / 0
Запрос на выборку. Как упростить?
    #39741135
Siompc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Кривцов Анатолий,
Есть recordset. То есть переходим на 20 запись в таблице и после в цикле проверяем следующие записи, пока не наберется 20 наименований?

Если я так это понял тогда тут несколько проблем. Например если для 1 страницы наберется по условию 20 наименований и последний код товара будет 35. например первой десятки товаров нет на складе. Он пропускаются. Тогда как recordset поймет, что нужно начать листать в цикле с 20 строчки?
И запомнить текущий номер строки так-же не может. Так как статус товара может за это время измениться.
...
Рейтинг: 0 / 0
Запрос на выборку. Как упростить?
    #39741155
alecko
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
из рекордсета можно заполнять массив - 20 строк или конец рекордсета.
...
Рейтинг: 0 / 0
Запрос на выборку. Как упростить?
    #39741253
Siompc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
alecko,

Вот это не понял. В смысле заполнять массив? Просто пролистывать строки и их сохранять в массив? У меня в функциях рекордсета нет никаких ограничений по выборке. Он просто получает данные из запроса и может пролистывать строки. Ну и считывать данные столбцов. Все равно прежде чем получить эти данные нужно выполнить запрос.
...
Рейтинг: 0 / 0
Запрос на выборку. Как упростить?
    #39741282
alecko
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Siompc, пролистать, проверить на соответствие условиям и заполнить 20 строк, если б задание было например 23 строки, то давно бы к этому пришли сами, я думаю
в следующий раз заполнять тот же массив, но очевидно уже следующими строками.
...
Рейтинг: 0 / 0
Запрос на выборку. Как упростить?
    #39741296
Фотография ПЕНСИОНЕРКА
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SiompcУ меня категории находятся в таблице товаров в виде строки
видимо у вас множественный выбор(подстановка) из новых версий аксесс
экономия на спичках
...
Рейтинг: 0 / 0
Запрос на выборку. Как упростить?
    #39741297
Siompc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
alecko,

Я так и делаю. Запрос, который третий, как раз и возвращает 20 строк, которые потом используются для отображения. Почему не получается просто так взять и без тройного запроса сделать тоже самое я писал чуть выше
...
Рейтинг: 0 / 0
Запрос на выборку. Как упростить?
    #39741298
Siompc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Я сейчас хочу попробовать обьединить все эти три запроса в один, что бы без сохранения кодов сразу получить заветные 20 наименований
...
Рейтинг: 0 / 0
Запрос на выборку. Как упростить?
    #39741299
Фотография ПЕНСИОНЕРКА
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SiompcЕсть таблицы товары и категории в базе access
может примерчик базы выложите, по десятку строк
...
Рейтинг: 0 / 0
25 сообщений из 26, страница 1 из 2
Форумы / Microsoft Access [игнор отключен] [закрыт для гостей] / Запрос на выборку. Как упростить?
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]