powered by simpleCommunicator - 2.0.52     © 2025 Programmizd 02
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Формирование запроса
12 сообщений из 12, страница 1 из 1
Формирование запроса
    #32090543
АндрейТ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день!
Предположим есть некая таблица,
id(уникальный записи)
id1 (№ карточки)
f1,f2 - поля карточки.
id id1 f1 f2
1 1 А1 С1
2 1 А2 С1
3 2 В1 Р1
4 3 X1 Z1
5 3 X1 Z2
...
В таблице хранятся карточки, которые могут состоять из
нескольких или одной записи (id1 - № карточки).
? как вытащить всю карточку, например по условию f1=А1,
т.е. получить должен две записи id=1 и id=2.
select * from t1 where id1 in (select distinct id1 from t1 where f1=А1)
Такой запрос правильный, но для больших таблиц (>400000) и внутренней выборке (2000) выполняется медленно, что на ORACLE,MSSQl, про IB вообще молчу. Индексы все есть. Какие есть еще варианты выполнения такого запроса или другой организации БД?
Вариант:
select b.* from test a inner join test b on a.id1 = b.id1 where a.f1=A1
замечательный, но возвращает много дублей, с которыми надо бороться.
Искренне признателен.
...
Рейтинг: 0 / 0
Формирование запроса
    #32090678
Gold
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как писал Алексей Ковязин, не вникая в подробности заменяй IN на EXISTS.
...
Рейтинг: 0 / 0
Формирование запроса
    #32090797
АндрейТ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Имхо, эти два запроса
select * from t1 where id1 in (select distinct id1 from t1 where f1=А1)
select b.* from t1 where exists (select id1 from t1 a where a.id1 = b.id1 and a.f1=A1)
ничем не отличаются. Внутренний и внешний запросы, но как говорит (Попов на ibase.ru и мой собственный опыт), на Ib (у меня клоны 6.0, может на 6.5 и 7.0 иначе) подзапрос фактически выполняется для каждой записи внешнего запроса.
По-этомв вариант:
select b.* from test a inner join test b on a.id1 = b.id1 where a.f1=A1
мне нравится больше, но как убрать дубли?
Добавление distinct ничего не дает, скорость падает стремительно.
...
Рейтинг: 0 / 0
Формирование запроса
    #32090930
Sergey Tulaev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сделай хранимую процедуру.
...
Рейтинг: 0 / 0
Формирование запроса
    #32090986
Привет!

Честно говоря, ломает разбираться в неформализованном описании твоей проблемы. На это же время нужно, причем непроизводительно затрачиваемое.

Вот если бы COPY-PASTE структуры таблиц, текст проблемного запроса, его план, результаты - что получается, и что нужно получить, тогда бы можно подумать над советом.

Ведь цель форума - обмен опытом и мнениями, а не бесплатное обучение. Есть тут изрядная разница.
Прежде всего в том, чтобы человек через полгода набрал в поиске слова по проблеме, а ему выдало бы четкие письма с рекомендациями и ясно сформулированными советами.

Пожалуйста, формулируйте вопросы абсолютно ясно и недвусмысленно, оформляйте их красиво...

Тогда и ответы будут ясными и четкими.

C уважением,
Алексей.
...
Рейтинг: 0 / 0
Формирование запроса
    #32090990
Gold
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
>Имхо, эти два запроса
>select * from t1 where id1 in (select distinct id1 from t1 where f1=А1)
>select b.* from t1 where exists (select id1 from t1 a where a.id1 = b.id1 and >a.f1=A1)
>ничем не отличаются.

Безобразие! Не разводите смуту!!! Эти эапросы отличаются кардинальным образом - запрос с IN заменяется на кучу проверок OR, а т.к. IB выполняет проверку всех логических выражений, то логично предположить, что запрос IN будет сильно тормозить.
Можно попробовать заменить на SOME/ANY - не помню, что эта двоица там делает. Где-то статья была по этому поводу, кажись на ibase.ru
...
Рейтинг: 0 / 0
Формирование запроса
    #32091298
АндрейТ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
>Алексей Ковязин.
>Ведь цель форума - обмен опытом и мнениями, а не бесплатное обучение. >Есть тут изрядная разница.
По правде говоря, я не думаю, что для меня здесь бесплатное обучение, несколько вариантов я сам привел. Просто, к слову.
Попробую изложить.
create table test(id integer, id_car integer, f_znak char(10), f2 char(10))
insert into test values (1, 1, 'A1', 'С1')
insert into test values (2, 1, 'А2', 'С1')
insert into test values (3, 2, 'В1', 'Р1')
insert into test values (4, 3, 'X1', 'Z1')
insert into test values (5, 3, 'X1', 'Z2')
Например, мы имеем объект автомобиль - карточка. Он сегодня имеет один госномер, завтра другой, послезавтра транзит. Сохраним эту историю в приведенной выше таблице. id - это просто уникальный ключ, id_car-идентификатор машины, f_znak - рег.знак, f2- любые другие поля.
Задаем условие поиска: f_znak like 'А1%'. Задача - получить не все записи, удовлетворяющие поставленным условиям, а полностью карточки.
При таком условии я должен получить две записи:
1,1,A1,C1
2,1,A2,C1
а не только ту, у которой id=1.
Эту задачу решает запрос:
select * from test where id_car in (select id_car from test where f_znak like 'A1%')
Но, как вы знаете, использование подзапросов в IB смерти подобно. По-этому я пытаюсь найти другой вариант SQL запроса, некоторого стандартного, пример я привел в других ответах. Использование tmp таблиц не очень разумно, выборки составляют до 10000 карточек, а хочется чтобы ответ был получен быстро.
Буду благодарен, если кто-нибудь поделится мыслями. Индексы специально не создавал.
...
Рейтинг: 0 / 0
Формирование запроса
    #32091309
АндрейТ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
>GOLD
Посмотрите план запроса
select a.* from test a where exists
(select id_car from test b where a.id_car = b.id_car and
b.f_znak like 'A1%')


PLAN (B NATURAL) PLAN (A NATURAL)
(natural - понятно, нет индексов), но суть то все равно одна и та же - внутренний подзапрос и внешний. Кроме того, я проверял выполнение на других, подобных, реальных данных, с индексами, очень много записей - время выполнения IN и EXISTS одно и тоже.
...
Рейтинг: 0 / 0
Формирование запроса
    #32091766
Привет!
таблица
Код: 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.
CREATE TABLE TESTCARD (
    ID      INTEGER NOT NULL,
    ID_CAR  INTEGER,
    F_ZNAK  CHAR( 10 ),
    F2      CHAR( 10 )
);





 /******************************************************************************/ 
 /*                                Primary Keys                                */ 
 /******************************************************************************/ 

ALTER TABLE TESTCARD ADD CONSTRAINT PK_TESTCARD PRIMARY KEY (ID);


 /******************************************************************************/ 
 /*                                  Indices                                   */ 
 /******************************************************************************/ 

CREATE INDEX TESTCARD_IDX1 ON TESTCARD (ID_CAR);
CREATE INDEX TESTCARD_IDX2 ON TESTCARD (F_ZNAK);
);


данные
Код: plaintext
1.
2.
3.
4.
5.
ID	ID_CAR	F_ZNAK	F2
 1 	 1 	A1	c1
 2 	 1 	A2	c1
 3 	 2 	B1	p1
 4 	 3 	X1	Z1
 5 	 3 	X1	Z2


запрос
Код: plaintext
1.
2.
3.
select tc.id, tc.id_car, tc.f_znak, tc.f2
from testcard tc
     join testcard tc2
      on (tc.id_car=tc2.id_car and tc2.f_znak like 'A1%')


План на yaffil 1.0
Код: plaintext
1.
2.
3.
4.
Plan
PLAN JOIN (TC2 INDEX (TESTCARD_IDX2),TC INDEX (TESTCARD_IDX1))

Adapted Plan
PLAN JOIN (TC2 INDEX (TESTCARD_IDX2),TC INDEX (TESTCARD_IDX1))


результаты

Код: plaintext
1.
2.
ID	ID_CAR	F_ZNAK	F2
 1 	 1 	A1	c1
 2 	 1 	A2	c1


И все же купи Грабера!
Примечание - yaffil на like в подходящих случаях использует индекс.


WBR,
Alexey.
...
Рейтинг: 0 / 0
Формирование запроса
    #32092218
АндрейТ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день, Алексей.
К сожалению,я забыл это повторить, Вы не обратили внимание на предыдущие письма, касательно дублей..
С Like 'A1%' у меня проблем не было. Проблемы с like 'X1%'
select tc.id, tc.id_car, tc.f_znak, tc.f2
from testcard tc
join testcard tc2
on (tc.id_car=tc2.id_car and tc2.f_znak like 'X1%')

ID ID_CAR F_ZNAK F2
4 3 X1 Z1
4 3 X1 Z1
5 3 X1 Z2
5 3 X1 Z2
Вопрос, как убрать дубли. Грабер советует делать запрос ассиметричным, вводом дополнительного условия. Но пример, приведенный им не подходит, надо чтобы и с A1 работало и с X1. Тем более, что это только маленькая часть таблицы, в ней гораздо больше полей. Вопрос чисто теоретический, как сделать так, чтобы при f_znak like 'A1%' возвращалось
ID ID_CAR F_ZNAK F2
1 1 A1 c1
2 1 A2 c1

а при f_znak like 'X1%'
ID ID_CAR F_ZNAK F2
4 3 X1 Z1
5 3 X1 Z2
Приведенный мной ранее запрос с подзапросом решает эту пробему, но на IB, при больших данных это смерти подобно, он внутренний подзапрос делает по индексу, в внешний natural.
Вот я и думаю, как решить эту проблему, вплоть до создания некой другой структуры хранения данных.
...
Рейтинг: 0 / 0
Формирование запроса
    #32092380
Код: plaintext
1.
2.
3.
select distinct tc.id, tc.id_car, tc.f_znak, tc.f2
from testcard tc
     join testcard tc2
      on (tc.id_car=tc2.id_car and (tc2.f_znak like 'X1%' ))


Код: plaintext
1.
2.
3.
4.
Plan
PLAN SORT (JOIN (TC2 INDEX (TESTCARD_IDX2),TC INDEX (TESTCARD_IDX1)))

Adapted Plan
PLAN SORT (JOIN (TC2 INDEX (TESTCARD_IDX2),TC INDEX (TESTCARD_IDX1)))


Код: plaintext
1.
2.
ID	ID_CAR	F_ZNAK	F2
 4 	 3 	X1	Z1
 5 	 3 	X1	Z2



К сожалению,я забыл это повторить, Вы не обратили внимание на предыдущие письма, касательно дублей..
С Like 'A1%' у меня проблем не было. Проблемы с like 'X1%'




Так какого же хрена, прошу прощения, приводить в письме #7 в данной теме, после настойчивой просьбы подробно и однозначно изложить проблему методом COPY-PASTE, появляется группа примеров с перемешанными русско-английскими буквами (ведь их исправлять пришлось для внесения в базу), да еще и с тестовым примером, скрывающим какую либо проблему?

Имхо, СРОЧНО нужно прочитать ВОТ ЭТУ СТАТЬЮ .

WBR,
Alexey
...
Рейтинг: 0 / 0
Формирование запроса
    #32092469
АндрейТ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Алексей, прошу прощения за COPY-PASTE ошибку, недоглядел. В письме №1 было все правильно.Обещаю, больше такое не повторится, буду точен и лаконичен, как спартанец.
Теперь по существу.
Вариант с distinct я знаю.
Он включает в себя сортировку. Я запускал подобный запрос на 300000 записей, вытащить надо было 3000 карточек. Запрос выполнялся очень долго, план запроса, тот же, что Вы и указали. Я вот думаю, есть ли какой-нибудь вариант с UNION, вначале добавить условие a.id!=b.id, это по идее должно сделать все правильно для X1, но для A1 вытащит только одну, или наоборот.
И добавить Union недостающите, но как?
Ну не дает мне покоя мысль, точно ли надо делать сортировку или промежуточную выборку для получения нужных мне данных. Нет ли другого варианта. В любом случае, обещаю, если найду - опубликую.
...
Рейтинг: 0 / 0
12 сообщений из 12, страница 1 из 1
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Формирование запроса
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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