Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / помогите определится у кого ошибка / 25 сообщений из 40, страница 1 из 2
24.07.2007, 17:35
    #34681096
Vivka
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите определится у кого ошибка
есть две таблицы:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
create table test_1 ( name char( 10 ), ku numeric( 4 ) , ku_1   numeric( 4 ) );
insert into test_1 (name,ku,ku_1)  values ('Петров',   1 ,   0 );
insert into test_1 (name,ku,ku_1)  values ('Иванов',   2 ,   0 );
insert into test_1 (name,ku,ku_1)  values ('Сидоров',  3 ,   0 );

create table test_2 (kh numeric( 13 ),  ku numeric( 4 ) , d_s timestamp );
insert into test_2 (kh,ku,d_s)  values ( 1 ,  1 , '2007-01-01');
insert into test_2 (kh,ku,d_s)  values ( 1 ,  2 , '2007-01-01');
insert into test_2 (kh,ku,d_s)  values ( 1 ,  3 , '2007-01-01');

а вот собственно сам хитрый запрос:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
select	test_1.name
from	test_1,
	test_2
where	test_2.kh =   1 			and
	test_2.ku between   1  and  100 	and
	test_1.ku = test_2.ku		and
	test_1.ku = 	(select min(t1.ku)
			from   test_1 t1,test_2 t2
			where	t1.ku_1 = test_1.ku_1	and
				t2.kh   = test_2.kh	and
				t2.d_s  = test_2.d_s	and
				t1.ku   = t2.ku )	
в моем понимании SQL должен вернуть одну строчку с минимальным KU т.е
Код: plaintext
"Петров    "
а он возвращает весь набор данных
Код: plaintext
1.
2.
"Петров    "
"Иванов    "
"Сидоров   "

по QUERY PLAN такое чувство что просто игнорирует подселект
Код: plaintext
1.
2.
3.
4.
5.
Nested Loop  (cost= 200000000 . 00 .. 200000068 . 18  rows= 6  width= 14 ) (actual time= 0 . 065 .. 0 . 131  rows= 3  loops= 1 )
  Join Filter: ("inner".ku = "outer".ku)
  ->  Seq Scan on test_2  (cost= 100000000 . 00 .. 100000031 . 18  rows= 1  width= 33 ) (actual time= 0 . 033 .. 0 . 042  rows= 3  loops= 1 )
        Filter: ((kh =  1 ::numeric) AND (ku >=  1 ::numeric) AND (ku <=  100 ::numeric))
  ->  Seq Scan on test_1  (cost= 100000000 . 00 .. 100000022 . 00  rows= 1200  width= 34 ) (actual time= 0 . 003 .. 0 . 007  rows= 3  loops= 3 )
Total runtime:  0 . 230  ms

собствено если закоментить одно условие в подселекте(которое по идеи не должно влиять на результат в данном случае)
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
select	test_1.name
from	test_1,
	test_2
where	test_2.kh =   1 			and
	test_2.ku between   1  and  100 	and
	test_1.ku = test_2.ku		and
	test_1.ku = 	(select min(t1.ku)
			from   test_1 t1,test_2 t2
			where	/*t1.ku_1 = test_1.ku_1	and*/
				t2.kh   = test_2.kh	and
				t2.d_s  = test_2.d_s	and
				t1.ku   = t2.ku )	
то он отрабытывается правильно
Код: plaintext
"Петров    "

И в этом случае QUERY PLAN становится похож на правду
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
Nested Loop  (cost= 200000000 . 00 .. 242200078935 . 98  rows= 6  width= 14 ) (actual time= 0 . 295 .. 0 . 525  rows= 1  loops= 1 )
  Join Filter: ("inner".ku = "outer".ku)
  ->  Seq Scan on test_2  (cost= 100000000 . 00 .. 242100078898 . 98  rows= 1  width= 33 ) (actual time= 0 . 235 .. 0 . 455  rows= 1  loops= 1 )
        Filter: ((kh =  1 ::numeric) AND (ku >=  1 ::numeric) AND (ku <=  100 ::numeric) AND ((subplan) = ku))
        SubPlan
          ->  Aggregate  (cost= 200000065 . 17 .. 200000065 . 18  rows= 1  width= 10 ) (actual time= 0 . 136 .. 0 . 137  rows= 1  loops= 3 )
                ->  Nested Loop  (cost= 200000000 . 00 .. 200000065 . 15  rows= 6  width= 10 ) (actual time= 0 . 033 .. 0 . 095  rows= 3  loops= 3 )
                      Join Filter: ("inner".ku = "outer".ku)
                      ->  Seq Scan on test_2 t2  (cost= 100000000 . 00 .. 100000028 . 15  rows= 1  width= 10 ) (actual time= 0 . 005 .. 0 . 012  rows= 3  loops= 3 )
                            Filter: ((kh = $ 0 ) AND (d_s = $ 1 ))
                      ->  Seq Scan on test_1 t1  (cost= 100000000 . 00 .. 100000022 . 00  rows= 1200  width= 10 ) (actual time= 0 . 002 .. 0 . 007  rows= 3  loops= 9 )
  ->  Seq Scan on test_1  (cost= 100000000 . 00 .. 100000022 . 00  rows= 1200  width= 24 ) (actual time= 0 . 002 .. 0 . 006  rows= 3  loops= 1 )
Total runtime:  0 . 649  ms

Версия сервака 8,1,4

Помогите кто чем сможет.
Заранее спасибо...
...
Рейтинг: 0 / 0
24.07.2007, 18:11
    #34681241
Thamerlan
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите определится у кого ошибка
Замена
Код: plaintext
test_1.ku =    (select min(t1.ku)
на
Код: plaintext
test_1.ku IN    (select min(t1.ku)
дает искомый результат,
но что-то мне не нравится в вашем SQL'е.
...
Рейтинг: 0 / 0
24.07.2007, 18:33
    #34681310
Vivka
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите определится у кого ошибка
ThamerlanЗамена
Код: plaintext
test_1.ku =    (select min(t1.ku)
на
Код: plaintext
test_1.ku IN    (select min(t1.ku)
дает искомый результат,
но что-то мне не нравится в вашем SQL'е.

согласен, есть еще куча вариантов замен и переписи SQL, чтоб он отрабатывал правильно.
Но что ему не нравится в исходном SQLе?? И как его заставить работать правильно не переписывая SQL?
...
Рейтинг: 0 / 0
25.07.2007, 09:16
    #34682036
_Андрей_М
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите определится у кого ошибка
А не путает ли планировщик t1.ku_1 и test_1.ku_1 в подзапросе? Т. е. test_1 берётся не из запроса, а из подзапроса?
...
Рейтинг: 0 / 0
25.07.2007, 12:32
    #34682654
Vivka
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите определится у кого ошибка
_Андрей_МА не путает ли планировщик t1.ku_1 и test_1.ku_1 в подзапросе? Т. е. test_1 берётся не из запроса, а из подзапроса?

В том то и дело что не путает, а по QUERY PLAN он подзапрос просто игнорирует.
Что -то я вообще перестал понимать как работает сервак,
в этом случае ему плевать на case и он выдает все строки , хотя по идее результат СКЛ ничего не должен вернуть, т.к. нет записей с ku = -1 и test_1.ku = null.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
select	test_1.name
from	test_1,
	test_2
where	test_2.kh =   1 			and
	test_2.ku between   1  and  100 	and
	test_1.ku = test_2.ku		and
	test_1.ku = case when test_1.ku is null 
			then  
				(select min(t1.ku)
			 	from   test_1 t1,test_2 t2
				 where	t1.ku_1 = test_1.ku_1	and
					t2.kh   = test_2.kh	and
					t2.d_s  = test_2.d_s	and
					t1.ku   = t2.ku )
			else - 1 
		     end 

а вот если заменить
Код: plaintext
case when test_1.ku is null 
на
Код: plaintext
case when false
то он уже отрабатывает нормально.
...
Рейтинг: 0 / 0
26.07.2007, 10:18
    #34684858
Vivka
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите определится у кого ошибка
Ну, я так понимаю, что походу это все-таки ошибка планировщика или оптимизатора.
Ни у кого, больше ни каких мыслей нет?
Интересно версия 8.2 себя также ведет?
...
Рейтинг: 0 / 0
26.07.2007, 11:52
    #34685246
Thamerlan
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите определится у кого ошибка
8.2.0 тоже возвращает все 3.
...
Рейтинг: 0 / 0
27.07.2007, 08:47
    #34687727
_Андрей_М
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите определится у кого ошибка
8.2.4 под winXP тоже. Интересно, что
Код: plaintext
1.
2.
	... test_1.ku >
 	(select min(t1.ku) ...
и
Код: plaintext
1.
2.
	... test_1.ku <
 	(select min(t1.ku) ...
работают правильно. Может, что-то в стандарте SQL поменялось? :))
...
Рейтинг: 0 / 0
27.07.2007, 09:10
    #34687754
_Андрей_М
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите определится у кого ошибка
Похоже, а понял в чём дело.
У Вас таблицы в подзапросе связаны с таблицей в основном запросе, соответственно, select min(t1.ku) отрабатывает не для всей таблицы (точнее, соединения таблиц), а только для текущей записи.
Хотя, тогда непонятно, почему IN работает.
...
Рейтинг: 0 / 0
27.07.2007, 10:48
    #34688063
Vivka
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите определится у кого ошибка
_Андрей_МПохоже, а понял в чём дело.
У Вас таблицы в подзапросе связаны с таблицей в основном запросе, соответственно, select min(t1.ku) отрабатывает не для всей таблицы (точнее, соединения таблиц), а только для текущей записи.
Хотя, тогда непонятно, почему IN работает.

По идее подзапрос и должен отрабатывать для каждой строки, и для каждой строки должен вернуть минимальную t1.ku , в данном случае одну и ту же, равной единице.
Но видимо сервер думает что умнее нас, типа ему подсовывают "масло - масляное" и подзапрос вообще не выполняет. Если в СКЛ добавить явную ошибку, то он все равно отработает)).
Код: plaintext
1.
2.
3.
4.
5.
6.
...
test_1.ku  = (select min(t1.ku)
			from   test_1 t1,test_2 t2
			where	t1.ku_1 = test_1.ku_1	and test_1.name::numeric= 0  and
				t2.kh   = test_2.kh	and
				t2.d_s  = test_2.d_s	and
				t1.ku   = t2.ku ) ...
А вот с test_1.ku in (select min(t1.ku) он тут само собой ломается.

Помогает еще ему прочухаться конвертирование test_1.ku в другой тип,
например с test_1.ku::int8 = (select min(t1.ku) тоже отрабатывает правильно

Мне кажется что оптимизатор ошибочно думает что условие test_1.ku = test_2.ku равнозначно условию test_1.ku = (select min(t1.ku) . Типа тут избыточность и он не исполняет подзапрос. Как видно ему помагает изменение каких либо условий сравнения предикатов. Например изменение сравнения для подзапроса на in или конвертирование типа test_1.ku ( в одном из условий сравнения ), а вот если написать так
Код: plaintext
1.
test_1.ku::int8 = test_2.ku		and
test_1.ku::int8 = 	(select min(t1.ku)...
то он опять начинает криво работать
...
Рейтинг: 0 / 0
27.07.2007, 10:54
    #34688093
4321
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите определится у кого ошибка
Vivka
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
	test_1.ku = case when test_1.ku is null 
			then  
				(select min(t1.ku)
			 	from   test_1 t1,test_2 t2
				 where	t1.ku_1 = test_1.ku_1	and
					t2.kh   = test_2.kh	and
					t2.d_s  = test_2.d_s	and
					t1.ku   = t2.ku )
			else - 1 
		     end 

я ваще-то не понимаю, что вы тут обсуждаете, потому как обсуждать работу
Код: plaintext
NULL= (SELECT min()... )
- трудно, кроме, разве что, как на голубом глазу. (А именно такое в случае case when test_1.ku is null мы и имеем.)

если же имеется в виду какое-то другое написание запроса - приведите. будем посмотреть.
...
Рейтинг: 0 / 0
27.07.2007, 11:08
    #34688154
Vivka
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите определится у кого ошибка
4321я ваще-то не понимаю, что вы тут обсуждаете, потому как обсуждать работу
Код: plaintext
NULL= (SELECT min()... )
- трудно, кроме, разве что, как на голубом глазу. (А именно такое в случае case when test_1.ku is null мы и имеем.)

если же имеется в виду какое-то другое написание запроса - приведите. будем посмотреть.

ОК.
test_1.ku = case when test_1.ku is null заменить на test_1.ku = case when test_1.name is null .
...
Рейтинг: 0 / 0
27.07.2007, 11:53
    #34688383
_Андрей_М
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите определится у кого ошибка
Я имел в виду, что в подзапросе обрабатывается одна запись. А для одной записи min(t1.ku) = t1.ku.
Так как записи запроса и подзапроса связаны, то для Петрова min(t1.ku) = 1, для Иванова - 2, для Сидорова - 3. Вот они все и выводятся.
...
Рейтинг: 0 / 0
27.07.2007, 12:06
    #34688429
st_serg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите определится у кого ошибка
проверил на oracle, действительно, такое ощущение что pg просто откидывает часть условия с подзапросом...
...
Рейтинг: 0 / 0
27.07.2007, 12:13
    #34688467
Vivka
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите определится у кого ошибка
Если б записи запроса и подзапроса были связаны по ku - то согласен, а они связаны по ku_1 !.
Т.Е по логике у подзапроса есть три аргумента test_1.ku_1 , test_2.kh, test_2.d_s, и все три аргумента, для всех вариантов записей запроса, имеют одинаковое значение 0, 1, '2007-01-01', и подзапрос по идеи должен для каждой записи запроса приводится к виду
Код: plaintext
1.
2.
3.
4.
5.
select min(t1.ku)
			 	from   test_1 t1,test_2 t2
				 where	t1.ku_1 =  0 	and
					t2.kh   =  1 	and
					t2.d_s  ='2007-1-1'	and
					t1.ku   = t2.ku 
и всегда выдавать min(t1.ku) равной 1
...
Рейтинг: 0 / 0
27.07.2007, 12:15
    #34688476
Vivka
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите определится у кого ошибка
st_sergпроверил на oracle, действительно, такое ощущение что pg просто откидывает часть условия с подзапросом...
Ну да я тоже проверял и на SYBASE и на MSSQL. Все отрабатывают как надо, один pg умничает))
...
Рейтинг: 0 / 0
27.07.2007, 12:36
    #34688585
Ёш
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите определится у кого ошибка
Vivka st_sergпроверил на oracle, действительно, такое ощущение что pg просто откидывает часть условия с подзапросом...
Ну да я тоже проверял и на SYBASE и на MSSQL. Все отрабатывают как надо, один pg умничает))если Вы ещё не написали багрепорт, пожалуйста, напишите его вот сюда: http://archives.postgresql.org/pgsql-bugs/ (форма для отправки багрепорта собственно тут - http://www.postgresql.org/support/submitbug ) приложите к сообщению об ошибке схему базы и тестовые данные (как в Вашем первом сообщении, только русский текст лучше заменить на транслит так как не у всех есть русские шрифты)

ps: если Вам трудно написать по английски - пожалуйста напишите по русски сдесь (или мне личным сообщением) - я переведу на английский и отправлю багрепорт.
...
Рейтинг: 0 / 0
27.07.2007, 12:52
    #34688669
Vivka
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите определится у кого ошибка
Не писал и не буду, с английским туго. Если у кого есть желания написать, пишите. В принципе вся инфа есть в первом сообщении.
...
Рейтинг: 0 / 0
27.07.2007, 14:46
    #34689277
Ёш
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите определится у кого ошибка
отправил

кстати, нашёл помоему похожую ошибку - http://archives.postgresql.org/pgsql-bugs/2007-07/msg00073.php ("Query Error : plan should not reference subplan's" - уже исправили вроде, по крайней мере там есть патч Тома) про проблемы с min max и "the older code for Param assignment". я не особо вникал, посмотри, может быть это аналогично тому с чем ты столкнулся и может этот патч тебе поможет :)

--
„Истина — это вовсе не то, что можно убедительно доказать, это то, что
делает всё проще и понятнее“ — Антуан де Сент-Экзюпери
...
Рейтинг: 0 / 0
27.07.2007, 15:07
    #34689380
Thamerlan
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите определится у кого ошибка
Ёшотправил


Запостите пожалуйста URL на созданный вами BR.
...
Рейтинг: 0 / 0
27.07.2007, 15:52
    #34689575
4321
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите определится у кого ошибка
Ёш про проблемы с min max
ну, если переписать на ORDER .. DESC LIMIT 1 - проблема остается


забавный бажок. чинится вот так (лишние поля я выводил для посмотреть):

Код: plaintext
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.
select	test_1.name
,test_2.ku
,test_1.ku
,(select min(t1.ku)
			from   test_1 t1,test_2 t2
			where	t1.ku_1 = test_1.ku_1	and
				t2.kh   = test_2.kh	and
				t2.d_s  = test_2.d_s	and
				t1.ku   = t2.ku )
,(test_1.ku = 	(select min(t1.ku)
			from   test_1 t1,test_2 t2
			where	t1.ku_1 = test_1.ku_1	and
				t2.kh   = test_2.kh	and
				t2.d_s  = test_2.d_s	and
				t1.ku   = t2.ku  )	)
from	test_1,
	test_2
where	(test_2.kh =  1)
	and (test_2.ku between  1 and 100)
	and (test_1.ku = test_2.ku)
	and (test_1.ku + 0 = 	(select min(t1.ku)
			from   test_1 t1,test_2 t2
			where	t1.ku_1 = test_1.ku_1	and
				t2.kh   = test_2.kh	and
				t2.d_s  = test_2.d_s	and
				t1.ku   = t2.ku  )	)
судя по всему - напортачили с оптимайзером.
...
Рейтинг: 0 / 0
27.07.2007, 15:56
    #34689600
Dan Black
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите определится у кого ошибка
Уже кто-то отпостил багрепорт. Посмотрим, что умные люди скажут :)
Код: plaintext
1.
----------------------------
 Verba volent, scripta manent 
...
Рейтинг: 0 / 0
27.07.2007, 16:04
    #34689627
Ёш
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите определится у кого ошибка
Thamerlan Ёшотправил


Запостите пожалуйста URL на созданный вами BR. http://archives.postgresql.org/pgsql-bugs/2007-07/msg00136.php
...
Рейтинг: 0 / 0
27.07.2007, 16:53
    #34689849
4321
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите определится у кого ошибка
Dan BlackУже кто-то отпостил багрепорт. Посмотрим, что умные люди скажут :)
Код: plaintext
1.
----------------------------
 Verba volent, scripta manent 
ну, то что баг - это очевидно. (мораль - сложные запросы с подзапросами придется тестировать. иначе - яица под трамвай )


Интересно, что в селекте подзапроса можно прибавить что-нить к величине - подзапрос все равно не выполняется (если не прибавлять 0 к правой части).

а вот если переписать на джойн - то бага не будет. (если я, конечно же, правильно навскид переписал):
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
select	t_1.name
from	test_1 t_1
INNER  JOIN
	test_2 t_2
ON (t_1.ku = t_2.ku)
INNER JOIN 
	(select  min(t1.ku) as mku
	,t2.kh as t2kh
	,t1.ku_1 AS t1ku_1
	,t2.d_s AS t2d_s
		from   test_1 t1 JOIN test_2 t2
			ON (t1.ku = t2.ku) 
			
		GROUP BY t2.kh,t1.ku_1,t2.d_s
			
	) AS foo
ON 
	(t1ku_1  = t_1.ku_1)	and	
	t2d_s  = t_2.d_s
	and t2kh   = t_2.kh
where	(t_2.kh =  1)
	and (t_2.ku between  1 and 100)
	and (t_1.ku = t_2.ku)
	and ( t_1.ku    = mku)

и еще - при прибавлении 0 справа - имеем план похожий на замену =() на IN()
...
Рейтинг: 0 / 0
27.07.2007, 17:01
    #34689885
Dan Black
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите определится у кого ошибка
Если уж говорить о сложных запросах, то вышеописанный запрос ужасен на мой взгляд :)
Есть очень много спорных подходов, касающихся подзапроса и его использования в основном запросе (из серии почему используется =(), а не IN () )... да и сам подзапрос, а именно условия
Код: plaintext
1.
t2.kh   = test_2.kh	and
t2.d_s  = test_2.d_s	and
ИМХО лишние. Возможно там где-то есть индексы, которые должны использоваться, но их в исходных данных не видно.
Код: plaintext
1.
----------------------------
 Verba volent, scripta manent 
...
Рейтинг: 0 / 0
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / помогите определится у кого ошибка / 25 сообщений из 40, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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