powered by simpleCommunicator - 2.0.59     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / IBM DB2, WebSphere, IMS, U2 [игнор отключен] [закрыт для гостей] / В чем различие между двумя SQL-запросами?
15 сообщений из 15, страница 1 из 1
В чем различие между двумя SQL-запросами?
    #36185371
askfinder
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Имеется таблица с историей изменения документов. Поля таблицы: POL_ID (ID документа), POL_STA_ID (статус документа: -1 закрыт,0 приостановлен,1 активен), POL_JN_OPERATION (операция 1-добавлен,0 изменен,-1 удален,2 изменен статус), POL_JN_DATE_WRITE (TIMESTAMP операции) ну и прочие реквизиты. При изменении документа в историю пишется 2 (если меняется статус) либо 0 (если другие реквизиты). Активность документов может быть на время приостановлена (причем несколько раз). Нужно вытащить из нее документы в виде: ID-документа, Дата нач. действия, Дата окончания действия (т.е. промежутки времени в которых документ был активен). DB2 v.9.1.2 Win (Express-C). Делаю следующее:

SELECT TBL1.POL_ID,TBL1.POL_JN_DATE AS D_START,TBL2.POL_JN_DATE AS D_END
FROM
(SELECT POL_ID,POL_JN_DATE_WRITE FROM USRSCHEMA.HISTORY
WHERE POL_STA_ID=1 AND (POL_JN_OPERATION=1 OR POL_JN_OPERATION=2))
AS TBL1(POL_ID,POL_PEO_ID,POL_JN_DATE)
LEFT JOIN
(SELECT POL_ID,POL_JN_DATE_WRITE FROM USRSCHEMA.HISTORY
WHERE (POL_STA_ID=0 OR POL_STA_ID=-1) AND POL_JN_OPERATION=2)
AS TBL2(POL_ID,POL_PEO_ID,POL_JN_DATE)
ON TBL2.POL_ID=TBL1.POL_ID
WHERE
TBL2.POL_JN_DATE=(SELECT MIN(POL_JN_DATE_WRITE) FROM USRSCHEMA.HISTORY
WHERE (POL_STA_ID=0 OR POL_STA_ID=-1) AND POL_JN_OPERATION=2 AND
POL_JN_DATE_WRITE>TBL1.POL_JN_DATE)
OR TBL2.POL_JN_DATE IS NULL

Работает некорректно, такое впечатление, что не работает (POL_STA_ID=0 OR POL_STA_ID=-1) AND... во внешнем WHERE. Меняю WHERE во внешнем запросе - разделив его на два отдельных:

SELECT TBL1.POL_ID,TBL1.POL_JN_DATE AS D_START,TBL2.POL_JN_DATE AS D_END
FROM
(SELECT POL_ID,POL_JN_DATE_WRITE FROM USRSCHEMA.HISTORY
WHERE POL_STA_ID=1 AND (POL_JN_OPERATION=1 OR POL_JN_OPERATION=2))
AS TBL1(POL_ID,POL_PEO_ID,POL_JN_DATE)
LEFT JOIN
(SELECT POL_ID,POL_JN_DATE_WRITE FROM USRSCHEMA.HISTORY
WHERE (POL_STA_ID=0 OR POL_STA_ID=-1) AND POL_JN_OPERATION=2)
AS TBL2(POL_ID,POL_PEO_ID,POL_JN_DATE)
ON TBL2.POL_ID=TBL1.POL_ID
WHERE
TBL2.POL_JN_DATE=(SELECT MIN(POL_JN_DATE_WRITE) FROM USRSCHEMA.HISTORY
WHERE POL_STA_ID=0 AND POL_JN_OPERATION=2 AND
POL_JN_DATE_WRITE>TBL1.POL_JN_DATE)
OR
TBL2.POL_JN_DATE=(SELECT MIN(POL_JN_DATE_WRITE) FROM USRSCHEMA.HISTORY
WHERE POL_STA_ID=-1 AND POL_JN_OPERATION=2 AND
POL_JN_DATE_WRITE>TBL1.POL_JN_DATE
OR
TBL2.POL_JN_DATE IS NULL

Работает корректно. Пз, натолкните на ответ - Почему? Чего я не вижу? На мой взгляд оба запроса эквивалентны.
...
Рейтинг: 0 / 0
В чем различие между двумя SQL-запросами?
    #36185465
BuryCommoner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
По-моему во втором запросе не хватает закрывающей скобки, но это не важно. В первом случае подзапрос
Код: plaintext
1.
2.
(SELECT MIN(POL_JN_DATE_WRITE) FROM USRSCHEMA.HISTORY
WHERE (POL_STA_ID= 0  OR POL_STA_ID=- 1 ) AND POL_JN_OPERATION= 2  AND
POL_JN_DATE_WRITE>TBL1.POL_JN_DATE)
в любом случае вернёт одно значение, ведь выбираете MIN(). Следовательно во втором случае два подзапроса
Код: plaintext
1.
2.
(SELECT MIN(POL_JN_DATE_WRITE) FROM USRSCHEMA.HISTORY
WHERE POL_STA_ID= 0  AND POL_JN_OPERATION= 2  AND
POL_JN_DATE_WRITE>TBL1.POL_JN_DATE)
и
Код: plaintext
1.
2.
(SELECT MIN(POL_JN_DATE_WRITE) FROM USRSCHEMA.HISTORY
WHERE POL_STA_ID=- 1  AND POL_JN_OPERATION= 2  AND
POL_JN_DATE_WRITE>TBL1.POL_JN_DATE)
вернут два значения.

---------------------------------------------------------
IS NULL OR NOT IS NULL
...
Рейтинг: 0 / 0
В чем различие между двумя SQL-запросами?
    #36185548
askfinder
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
BuryCommonerПо-моему во втором запросе не хватает закрывающей скобки
Да, удалял лишнию информацию из копи/паста и снес случайно. Но это действительно не важно.

BuryCommoner
в любом случае вернёт одно значение, ведь выбираете MIN(). Следовательно во втором случае два подзапроса вернут два значения.
Дык в том-то и дело что нужен ОДИН результат MIN(). Если есть в таблице две записи, в которых: в одной СТАТУС=-1, а в другой СТАТУС=0, подзапрос с MIN() выводит результат только для второй, а первую не видит в упор. Иными словами:
(XXX or YYY) and ... работает как (YYYY) and...
Т.е. если есть запись с POL_STA_ID=-1 (и с данным ID нет записей с POL_STA_ID=0) то

SELECT MIN(POL_JN_DATE_WRITE) FROM USRSCHEMA.POLICIES_JN
WHERE (POL_STA_ID=0 OR POL_STA_ID=-1) AND POL_JN_OPERATION=2 AND POL_JN_DATE_WRITE>TIMESTAMP('2009-09-08','00.00.00')

ничего не возвращает, а если наоборот - все нормально.
...
Рейтинг: 0 / 0
В чем различие между двумя SQL-запросами?
    #36185590
askfinder
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
К предыдущему собственному посту.

Отдельно

SELECT MIN(POL_JN_DATE_WRITE) FROM USRSCHEMA.POLICIES_JN
WHERE (POL_STA_ID=0 OR POL_STA_ID=-1) AND POL_JN_OPERATION=2 AND POL_JN_DATE_WRITE>TIMESTAMP('2009-09-08','00.00.00')

работает как и ожидается, но вот в весь запрос (с JOIN-ом) нет
...
Рейтинг: 0 / 0
В чем различие между двумя SQL-запросами?
    #36185632
BuryCommoner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
askfinderЕсли есть в таблице две записи, в которых: в одной СТАТУС=-1, а в другой СТАТУС=0, подзапрос с MIN() выводит результат только для второй, а первую не видит в упор.
Странно было бы ждать другого.

---------------------------------------------------------
IS NULL OR NOT IS NULL
...
Рейтинг: 0 / 0
В чем различие между двумя SQL-запросами?
    #36185787
askfinder
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
BuryCommonerСтранно было бы ждать другого.

? В JOIN-е то для конкретной записи есть только ОДИН вариант (СТАТУС=-1), почему его нет в результате? По логике, тогда не должно быть и результата для варианта с СТАТУС=0.
Возможно я не вполне ясно объяснил?

Есть записи для 4-х документов (ID, СТАТУС, ОПЕРАЦИЯ, TIMESTAMP):
1, 1, 1, 2009-08-08-00.00.00 -- добавлена запись в историю
1, -1, 2, 2009-08-09-02.00.00 -- изменен статус (закрыт)
2, 1, 1, 2009-08-08-00.00.00 -- добавлена запись в историю
2, 0, 2, 2009-08-09-01.00.00 -- изменен статус (приостановлен)
3, 1, 1, 2009-08-08-00.00.00 -- добавлена запись в историю
3, 0, 2, 2009-08-09-03.00.00 -- изменен статус (приостановлен)
3, 1, 2, 2009-08-09-05.00.00 -- изменен статус (восстановлен)
3, -1, 2, 2009-08-09-06.00.00 -- изменен статус (закрыт)
4, 1, 1, 2009-08-08-00.00.00 -- добавлена запись в историю

При этом первый вариант запроса возвращает результат в который включены записи с ID=2,3,4 но нет записи с ID=1 примерно такой (не пишу полностью дамп дабы не загромождать):
2 2009-08-08-00.00.00 2009-08-09-01.00.00
3 2009-08-08-00.00.00 2009-08-09-03.00.00
3 2009-08-09-05.00.00 2009-08-09-06.00.00
4 2009-08-08-00.00.00 -

второй вариант запроса возвращает результат для всех записей:
1 2009-08-08-00.00.00 2009-08-09-02.00.00
2 2009-08-08-00.00.00 2009-08-09-01.00.00
3 2009-08-08-00.00.00 2009-08-09-03.00.00
3 2009-08-09-05.00.00 2009-08-09-06.00.00
4 2009-08-08-00.00.00 -
...
Рейтинг: 0 / 0
В чем различие между двумя SQL-запросами?
    #36186127
BuryCommoner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Действительно странно. Пересобрать статистику пробовали? Может оптимизатор отбрасывает, по его мнению излишние условия, из-за чего и получается вместо (xxx OR yyy) and zzz - yyy and zzz.

---------------------------------------------------------
IS NULL OR NOT IS NULL
...
Рейтинг: 0 / 0
В чем различие между двумя SQL-запросами?
    #36186269
askfinder
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
[quot BuryCommoner]Действительно странно. Пересобрать статистику пробовали? Может оптимизатор отбрасывает, по его мнению излишние условия, из-за чего и получается вместо (xxx OR yyy) and zzz - yyy and zzz.

Статистика тут ни при чем т.к. во-первых менять логику запроса в зависимости от статистики это даже для сурового DB2-ного оптимизатора перебор, а во-вторых прежде чем создать топик еще раз все это воссоздал в отдельной таблице - результат тот же.
Сильно подозреваю, что таки где-то в логике запроса. Если "на пальцах", то я вижу запросы примерно так:

в первом запросе:
Запрос из (Множество А + Множество В)
Включить в результат:
если В1=Функция(без разницы Х или Y)

во втором запросе:
Запрос из (Множество А + Множество В)
Включить в результат:
если В1=Функция(Х) или В1=Функция(Y)

При этом в каждой записи из любого множества может быть только либо Х либо Y.
Может, не вполне удачно "нарисовал", но я старался :)
Так вот на мой взгляд оба запроса одинаковы, на взгляд DB2 - нет. Чего я упустил? Вначале все-таки выполняется JOIN, а затем внешний WHERE или не так?
...
Рейтинг: 0 / 0
В чем различие между двумя SQL-запросами?
    #36186945
BuryCommoner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
1. В ваших запросах неправильно сделаны алиасы для подзапросов. Там нужно убрать поле POL_PEO_ID. Но это, как уже говорилось, не важно :)
2. Оба запроса с точки зрения логики SQL различны, но с учётом бизнес-логики, по-моему, идентичны.
3. Я провёл тесты с вашими данными и вот что получилось:
Исходные данные
1, 1, 1, 2009-08-08-00.00.00 -- добавлена запись в историю
1, -1, 2, 2009-08-09-02.00.00 -- изменен статус (закрыт)
2, 1, 1, 2009-08-08-00.00.00 -- добавлена запись в историю
2, 0, 2, 2009-08-09-01.00.00 -- изменен статус (приостановлен)
3, 1, 1, 2009-08-08-00.00.00 -- добавлена запись в историю
3, 0, 2, 2009-08-09-03.00.00 -- изменен статус (приостановлен)
3, 1, 2, 2009-08-09-05.00.00 -- изменен статус (восстановлен)
3, -1, 2, 2009-08-09-06.00.00 -- изменен статус (закрыт)
4, 1, 1, 2009-08-08-00.00.00 -- добавлена запись в историю

Запрос номер раз:
2 2009-08-08 00:00:00.0 2009-08-09 01:00:00.0
3 2009-08-09 05:00:00.0 2009-08-09 06:00:00.0
4 2009-08-08 00:00:00.0

Запрос номер два:
1 2009-08-08 00:00:00.0 2009-08-09 02:00:00.0
2 2009-08-08 00:00:00.0 2009-08-09 01:00:00.0
3 2009-08-09 05:00:00.0 2009-08-09 06:00:00.0
4 2009-08-08 00:00:00.0

Похоже без поллитры не обойтись.

---------------------------------------------------------
IS NULL OR NOT IS NULL
...
Рейтинг: 0 / 0
В чем различие между двумя SQL-запросами?
    #36187179
BuryCommoner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Блин, ну и поломал же я голову :) Планы запросов полчаса изучал. У вас же в первом запросе в глобальном условии WHERE в подзапросе минимальная дата берётся со всей таблицы без привязки к конкретному документу. Второй запрос смотреть не стал, но похоже, что он тоже ошибочный.
P.S. когда добавил к подзапросу в глобальном WHERE условие POL_ID = TBL1.POL_ID, весь запрос перестал выполняться. Может там какое-то циклическое противоречие началось :)

---------------------------------------------------------
IS NULL OR NOT IS NULL
...
Рейтинг: 0 / 0
В чем различие между двумя SQL-запросами?
    #36187237
BuryCommoner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Попробуйте такой запрос:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
SELECT uh.pol_id, uh.pol_jn_date_write AS d_start, MIN(q.pol_jn_date_write) AS d_end
FROM usrschema.history uh
LEFT JOIN (
	SELECT uh1.pol_id, uh1.pol_jn_date_write
	FROM usrschema.history uh1
	WHERE uh1.pol_sta_id IN ( 0 , - 1 ) AND uh1.pol_jn_operation =  2 
	) q ON uh.pol_id = q.pol_id AND uh.pol_jn_date_write < q.pol_jn_date_write
WHERE uh.pol_sta_id =  1  AND uh.pol_jn_operation IN ( 1 ,  2 )
GROUP BY uh.pol_id, uh.pol_jn_date_write

---------------------------------------------------------
IS NULL OR NOT IS NULL
...
Рейтинг: 0 / 0
В чем различие между двумя SQL-запросами?
    #36187593
askfinder
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Извиняюсь за задержку - Инет только на работе.

BuryCommoner У вас же в первом запросе в глобальном условии WHERE в подзапросе минимальная дата берётся со всей таблицы без привязки к конкретному документу.
Т.е. POL_JN_DATE_WRITE>TBL1.POL_JN_DATE не катит? Этой конструкцией я как раз и пытался сделать привязку.

BuryCommoner
Попробуйте такой запрос:

Работает, проверил на реальных данных. Большое спасибо.
...
Рейтинг: 0 / 0
В чем различие между двумя SQL-запросами?
    #36187604
askfinder
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
askfinder Этой конструкцией я как раз и пытался сделать привязку.
Еще раз проанализировал и вопросов меньше не стало. Действительно, минимальная берется со всей таблице (что собссно без разницы для бизнес-логики - нужно только одно значение) но ведь:
1. POL_JN_DATE_WRITE>TBL1.POL_JN_DATE разве не говорит что минимальную дату нужно искать по всей истории для записей именно из TBL1?
2. Если нет, то каким образом в результат попадают именно правильные значения, а не "с потолка"?
3. Если да, то почему такая "избирательность" отбора записей?
Если для документа есть записи где СТАТУС=0 и СТАТУС=-1 (да любое другое их сочетание), все работает корректно, если есть только СТАТУС=-1 - фигня получается. Вот это больше всего и не понятно.
...
Рейтинг: 0 / 0
В чем различие между двумя SQL-запросами?
    #36187683
BuryCommoner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сначала были соединены записи из двух подзапросов tbl1 И tbl2 по полю pol_id. Потом они фильтруются. Остаются те, где TBL2.POL_JN_DATE пустое и те, для которых выполняется условие:

Код: plaintext
1.
2.
TBL2.POL_JN_DATE=(SELECT MIN(POL_JN_DATE_WRITE) FROM USRSCHEMA.HISTORY
WHERE (POL_STA_ID= 0  OR POL_STA_ID=- 1 ) AND POL_JN_OPERATION= 2  AND
POL_JN_DATE_WRITE>TBL1.POL_JN_DATE)

то есть TBL2.POL_JN_DATE должна точно совпадать с минимальной POL_JN_DATE_WRITE в таблице. Причем минимальное POL_JN_DATE_WRITE берется для ВСЕХ документов, а не только для тех у которых POL_ID совпадает с соединенными подзапросами. Следовательно, не во всех случаях значение MIN(POL_JN_DATE_WRITE) выбранное из ВСЕХ документов, будет равно POL_JN_DATE_WRITE документа в ткущей строке.

---------------------------------------------------------
IS NULL OR NOT IS NULL
...
Рейтинг: 0 / 0
В чем различие между двумя SQL-запросами?
    #36187986
askfinder
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
BuryCommonerПричем минимальное POL_JN_DATE_WRITE берется для ВСЕХ документов, а не только для тех у которых POL_ID совпадает с соединенными подзапросами.
Хм. А как быть с POL_JN_DATE_WRITE> TBL1.POL_JN_DATE ? Кроме того
BuryCommonerне во всех случаях значение MIN(POL_JN_DATE_WRITE) выбранное из ВСЕХ документов, будет равно POL_JN_DATE_WRITE документа в ткущей строке.
было бы для РАЗНЫХ записей а не только для определенного типа. Если взять большее число записей, то закономерность четко прослеживается. Для меня во всяком случае, все это весьма не очевидно.
В принципе, решение проблемы уже было, теперь есть еще одно (Ваше более оптимально по крайней мере с точки зрения затрат), просто хотелось понять логику.
...
Рейтинг: 0 / 0
15 сообщений из 15, страница 1 из 1
Форумы / IBM DB2, WebSphere, IMS, U2 [игнор отключен] [закрыт для гостей] / В чем различие между двумя SQL-запросами?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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