powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Помогите составить запрос
25 сообщений из 26, страница 1 из 2
Помогите составить запрос
    #39611093
svnvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Упрощу структуру, чтобы не путаться в специфике базы:
Есть таблица master m и detail d.
Нужно вывести запрос строк из master + значение, говорящее о том, что для master СУЩЕСТВУЮТ значения в detail-таблице, и при этом дата окончания ни в одном из них непустая.
Сейчас запрос выглядит следующим образом:
авторSELECT m.*, (IF ((d_ex.id IS NOT NULL) AND (d_nul.id IS NULL), 'Y', 'N')) AS all_finished // lдетайлы существуют и нет незавершенных
FROM master m
LEFT JOIN detail d_ex ON d_ex.master_id = m.id // существование детайлов
LEFT JOIN detail d_nul ON (d_nul.master_id = m.id) AND ((d_nul.finish_time = '1899-12-30') OR (d_nul.finish_time IS NULL)) // присутствие незавершенных среди существующих

Однако выполняется он очень долго - 14 секунд.
Как только закомментируешь хотя бы один из этих джойнов, скорость возрастает до 2 секунд.
Но как тогда вместить все в один джойн, если это противоположные требования? В первом надо определить существование, а во втором - несуществование.
...
Рейтинг: 0 / 0
Помогите составить запрос
    #39611098
svnvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Упрощу структуру, чтобы не путаться в специфике базы:
Есть таблица master m и detail d.
Нужно вывести запрос строк из master + значение, говорящее о том, что для master СУЩЕСТВУЮТ значения в detail-таблице, и при этом дата окончания ни в одном из них непустая.
Сейчас запрос выглядит следующим образом:

Код: sql
1.
2.
3.
4.
SELECT m.*, (IF ((d_ex.id IS NOT NULL) AND (d_nul.id IS NULL), 'Y', 'N')) AS all_finished // lдетайлы существуют и нет незавершенных
FROM master m
LEFT JOIN detail d_ex ON d_ex.master_id = m.id // существование детайлов
LEFT JOIN detail d_nul ON (d_nul.master_id = m.id) AND ((d_nul.finish_time = '1899-12-30') OR (d_nul.finish_time IS NULL)) // присутствие незавершенных среди существующих



Однако выполняется он очень долго - 14 секунд.
Как только закомментируешь хотя бы один из этих джойнов, скорость возрастает до 2 секунд.
Но как тогда вместить все в один джойн, если это противоположные требования? В первом надо определить существование, а во втором - несуществование.
...
Рейтинг: 0 / 0
Помогите составить запрос
    #39611106
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
svnvladЕсть таблица master m и detail d.
Нужно вывести запрос строк из master + значение, говорящее о том, что для master СУЩЕСТВУЮТ значения в detail-таблице, и при этом дата окончания ни в одном из них непустая.

Код: sql
1.
2.
3.
4.
5.
SELECT m.*
     , MAX(d.master_id) IS NULL DetailsNotExist
     , MAX(d.finish_time) > '1899-12-30' NullsNotExist
FROM master m
LEFT JOIN detail d ON d.master_id = m.id
...
Рейтинг: 0 / 0
Помогите составить запрос
    #39611110
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Одно плохо - значения-признаки будут дублироваться в каждой записи... некошерно... почему не получить их вторым запросом?
...
Рейтинг: 0 / 0
Помогите составить запрос
    #39611112
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А, да... GROUP BY m.id либо просто DISTINCT добавь. А то для тех записей, для которых есть соответствия более одного, вылезут дубли.
...
Рейтинг: 0 / 0
Помогите составить запрос
    #39611117
svnvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AkinaА, да... GROUP BY m.id либо просто DISTINCT добавь. А то для тех записей, для которых есть соответствия более одного, вылезут дубли.
Да, там есть, я просто забыл здесь написать.
...
Рейтинг: 0 / 0
Помогите составить запрос
    #39611237
svnvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AkinaОдно плохо - значения-признаки будут дублироваться в каждой записи... некошерно... почему не получить их вторым запросом?
Это сообщение не понял.
...
Рейтинг: 0 / 0
Помогите составить запрос
    #39611247
svnvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AkinasvnvladЕсть таблица master m и detail d.
Нужно вывести запрос строк из master + значение, говорящее о том, что для master СУЩЕСТВУЮТ значения в detail-таблице, и при этом дата окончания ни в одном из них непустая.

Код: sql
1.
2.
3.
4.
5.
SELECT m.*
     , MAX(d.master_id) IS NULL DetailsNotExist
     , MAX(d.finish_time) > '1899-12-30' NullsNotExist
FROM master m
LEFT JOIN detail d ON d.master_id = m.id


Если первое верно MAX(d.master_id) IS NULL DetailsNotExist,
то второе MAX(d.finish_time) > '1899-12-30' NullsNotExist не дает правильного результата.
...
Рейтинг: 0 / 0
Помогите составить запрос
    #39611265
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
svnvladMAX(d.finish_time) > '1899-12-30' NullsNotExist не дает правильного результата.
Да, точно. Замени на
Код: sql
1.
MIN(COALESCE(d.finish_time, '1899-12-30')) > '1899-12-30' NullsNotExist
...
Рейтинг: 0 / 0
Помогите составить запрос
    #39611266
svnvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
EMS MySQL Manager странно работает. Вношу с его помощью в дату значение '1899-30-12 00:00:00', он превращает его в 0000-00-00 00:00:00', соответственно, запрос его не находит как WHERE finish_time = '1899-12-30', однако, находит как WHERE finish_time = 0.
С другой стороны, в базе реально есть значения "1899-12-30 00:00:00", и их он находит как WHERE finish_time = '1899-12-30'.
Получается на нулевое значение даты надо проверять по 3-м признакам?
1. NULL
2. 1899-12-30
3. 0
...
Рейтинг: 0 / 0
Помогите составить запрос
    #39611271
svnvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Akina,
а вот так тоже нормально?
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
SELECT m.*,
       MAX(d.master_id) IS NULL DetailsNotExist,

       EXISTS(SELECT d.id FROM detail d 
              WHERE d.master_id = m.id
              AND ((d.finish_time IS NULL) OR (d.finish_time = 0) OR (d.finish_time = '1899-12-30'))) NullsExist

FROM master m
LEFT JOIN detail d ON d.master_id = m.id
GROUP BY m.id
...
Рейтинг: 0 / 0
Помогите составить запрос
    #39611290
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
svnvladа вот так тоже нормально?Нет. Коррелированный подзапрос скорее всего снизит скорость выполнения. SUM(условие1 OR условие2 OR ...) скорее всего будет быстрее.

svnvladEMS MySQL Manager странно работает. Вношу с его помощью в дату значение '1899-30-12 00:00:00', он превращает его в 0000-00-00 00:00:00'
https://dev.mysql.com/doc/refman/5.7/en/datetime.html Invalid DATE, DATETIME, or TIMESTAMP values are converted to the “zero” value of the appropriate type ('0000-00-00' or '0000-00-00 00:00:00').
Опять же смотрим SQL Modes.
И эта... какой точно тип данных у поля?
...
Рейтинг: 0 / 0
Помогите составить запрос
    #39611323
svnvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Akina,

тип DATETIME.
...
Рейтинг: 0 / 0
Помогите составить запрос
    #39611326
svnvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Немного усложним задачу. На самом деле в таблице detail не одна ссылка master_id, а две.
from_master_id и to_master_id. Заполняется только одна из них, либо from_master_id, либо to_master_id.
Соответственно, другая будет Null.
И тут у меня возникают трудности, как данный запрос адаптировать к этой системе.
...
Рейтинг: 0 / 0
Помогите составить запрос
    #39611346
svnvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вроде бы решил
Код: sql
1.
2.
3.
4.
5.
6.
7.
SELECT m.*,
MAX(COALESCE(d.from_master_id, d.to_master_id)) IS NOT NULL DetailsExist,
MIN(COALESCE(d.finish_time, '1899-12-30')) > '1899-12-30' NullsNotExist

FROM master m
LEFT JOIN detail d ON m.id IN (d.from_master_id, d.to_master_id)
GROUP BY m.id
...
Рейтинг: 0 / 0
Помогите составить запрос
    #39611347
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
svnvladтип DATETIME.
https://dev.mysql.com/doc/refman/5.7/en/datetime.html The DATETIME type is used for values that contain both date and time parts. MySQL retrieves and displays DATETIME values in 'YYYY-MM-DD HH:MM:SS' format. The supported range is '1000-01-01 00:00:00' to '9999-12-31 23:59:59'.
Так что '1899-30-12 00:00:00' - вполне себе легитимное значение для этого типа поля. А наблюдаемая проблема - хороший повод деинсталлировать глючный софт и перейти на нечто более вменяемое.

svnvladНа самом деле в таблице detail не одна ссылка master_id, а две.
from_master_id и to_master_id. Заполняется только одна из них, либо from_master_id, либо to_master_id.
Соответственно, другая будет Null.Ну привязывай две копии и используй COALESCE для выбора Not-NULL значения из двух. Делов-то... впрочем, что бы с учётом этого бреда не подумать об изменении структурки?
...
Рейтинг: 0 / 0
Помогите составить запрос
    #39611354
svnvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Akinasvnvladтип DATETIME.
https://dev.mysql.com/doc/refman/5.7/en/datetime.html The DATETIME type is used for values that contain both date and time parts. MySQL retrieves and displays DATETIME values in 'YYYY-MM-DD HH:MM:SS' format. The supported range is '1000-01-01 00:00:00' to '9999-12-31 23:59:59'.
Так что '1899-30-12 00:00:00' - вполне себе легитимное значение для этого типа поля. А наблюдаемая проблема - хороший повод деинсталлировать глючный софт и перейти на нечто более вменяемое.

Да он еще при добавлении или изменении записей в таблицы, даже если фиксируешь транзакцию, в упор не видит изменений, пока не отсоединишься от базы и не присоединишься вновь. А какой софт не глючный, конкурентоспособный по сравнению с EMS?

svnvladНа самом деле в таблице detail не одна ссылка master_id, а две.
from_master_id и to_master_id. Заполняется только одна из них, либо from_master_id, либо to_master_id.
Соответственно, другая будет Null.Ну привязывай две копии и используй COALESCE для выбора Not-NULL значения из двух. Делов-то... впрочем, что бы с учётом этого бреда не подумать об изменении структурки?
Там выше, уже решил.
По поводу структуры, тут master - это карточка груза (включает местоположение), а detail - это операции перегрузки, в ней отражается с какой карточки в какую груз был перегружен. Поэтому, собственно, сама карточка остается master-ом, а в detaile две ссылки - на карточку "откуда", и на карточку "куда".
...
Рейтинг: 0 / 0
Помогите составить запрос
    #39611455
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
svnvladкакой софт не глючный, конкурентоспособный по сравнению с EMS?А это от необходимого функционала зависит. Но со штатными консолью и воркбенчем такой хни, как ты рассказываешь, точно не бывает...
...
Рейтинг: 0 / 0
Помогите составить запрос
    #39611456
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
svnvladdetail - это операции перегрузки, в ней отражается с какой карточки в какую груз был перегружен.Избыточно и потенциально противоречиво. Достаточно информации, куда. А откуда - определяется уже имеющимися данными.
...
Рейтинг: 0 / 0
Помогите составить запрос
    #39611469
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AkinaТак что '1899-30-12 00:00:00' - вполне себе легитимное значение для этого типа поля.Не понял, почему? 30 месяц не бывает же?
...
Рейтинг: 0 / 0
Помогите составить запрос
    #39611475
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miksoftпочему? 30 месяц не бывает же?Блин, даже не посмотрел... вначале ж везде '1899-12-30' было... раз проверил и забыл.
...
Рейтинг: 0 / 0
Помогите составить запрос
    #39611827
svnvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Akinasvnvladdetail - это операции перегрузки, в ней отражается с какой карточки в какую груз был перегружен.Избыточно и потенциально противоречиво. Достаточно информации, куда. А откуда - определяется уже имеющимися данными.
А как отобразить такой процесс?
Приехало 10 автомобилей с грузом. Каждая партия этого груза - это отдельная карточка. В данном случае на одном автомобиле одна карточка груза. Включает в себя номер договора, вес, условия перевозки, ссылка на автомобиль.
Эти 10 авто разгружают на склад №1 в одну кучу, формируя таким образом новую карточку - карточку груза склада. Она включает номер договора, вес (в ней уже суммированные веса всех 10 партий), № склада.
В существующей схеме в таблице transshipment имеется ссылка from_cargo_card_id и to_cargo_card_id. Соответственно в ней сформируется 10 строк, отражающих историю всех перегрузок, их продолжительность, ответственного и т.д.
...
Рейтинг: 0 / 0
Помогите составить запрос
    #39611833
svnvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А еще один автомобиль могут разгружать не единоразово, а в 2 смены. В transshipment сформируется тогда 2 записи, отражающие историю всей перегрузки. А если просто в карточке делать ссылку "куда", то 2 операции не отобразить.
...
Рейтинг: 0 / 0
Помогите составить запрос
    #39611835
svnvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
И еще теоретически могут карточку одного автомобиля разгрузить частично на один склад, частично на другой, т.е. в 2 разных карточки.
...
Рейтинг: 0 / 0
Помогите составить запрос
    #39611893
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тебе надо почитать про складской учёт. Причём почитать серьёзно. А хранить или возить - совершенно неважно.
...
Рейтинг: 0 / 0
25 сообщений из 26, страница 1 из 2
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Помогите составить запрос
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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