-
Есть таблица - список слов
CREATE TABLE TMP_WORDS (
WORD_NUM INTEGER NOT NULL,
WORD_BODY VARCHAR_255 /* VARCHAR_255 = VARCHAR(255) */,
NEXT_WORD_NUM INTEGER
);
и таблица объектов с именами
CREATE TABLE OBJECTS (
ID INTEGER NOT NULL,
NAME D_NODE_NAME /* D_NODE_NAME = CHAR(1000) */
);
задача - выбрать из таблицы объектов те, которые содержать все слова из таблицы списка слов
Написал такое рекурсивное CTE :
For
with recursive
Check_Words AS
(
select
t_w.word_num,
t_w.next_word_num,
objects.id as objects_id,
objects.name as objects_name,
t_w.word_body
from tmp_words t_w
inner join objects on (Upper(objects.name) like ('%' || upper(t_w.word_body) || '%'))
where (t_w.word_num = 0)
UNION ALL
select
t_w.word_num,
t_w.next_word_num,
objects.id as objects_id,
objects.name as objects_name,
t_W.word_body
from tmp_words t_w
inner join objects on (Upper(objects.name) like ('%' || upper(t_w.word_body) || '%'))
inner JOIN Check_Words cc_ww
ON
(
(t_w.word_num = CC_WW.NEXT_WORD_NUM ) and
(
objects_id = CC_WW.objects_id
)
)
)
select distinct
FF_WW.objects_id,
FF_WW.word_num,
FF_WW.objects_name
from Check_Words FF_WW
INTO
:ob_glos_objects_id,
:ps,
:GLOS_WORD_S
Do
begin
if (not (ps is NULL)) then
if (ps = cnt_wrds - 1) then
suspend;
end
exit;
end
В результате получается набор, в котором записи, включающие хотя бы одно слово из таблицы слов,
т.е., похоже, что требование
from tmp_words t_w
inner join objects on (Upper(objects.name) like ('%' || upper(t_w.word_body) || '%'))
inner JOIN Check_Words cc_ww
ON
(
(t_w.word_num = CC_WW.NEXT_WORD_NUM ) and
(
objects_id = CC_WW.objects_id
)
)
игнорируется.
Как это понимать и что исправить?
-
-
т.е., похоже, что требование игнорируется.
сервер не может ничего игнорировать в принципе.
что ты написал то ты от него и получил.
-
> rrrrr © (12.04.17 13:43) [2]
Полезное замечание.
-
однажды один мальчик написал "селект все фром тэйблА",
но сервер проигнорировал его требование и вернул мальчику все строки из тэйблБэ
т.е., похоже, что требование
from tmp_words t_w
inner join objects on (Upper(objects.name) like ('%' || upper(t_w.word_body) || '%'))
inner JOIN Check_Words cc_ww
ON
(
(t_w.word_num = CC_WW.NEXT_WORD_NUM ) and
(
objects_id = CC_WW.objects_id
)
)
игнорируется.
с чего вдруг оно игнорируются?
воочию наблюдаешь строки для которых равенство или лайк не выполняется но в выборке они есть?
-
select *
from objects
where id not in (select id
from objects o
where exists(select null
from tmp_words
where o.name not like '%' || word_body || '%'
)
)
-
> rrrrr © (12.04.17 14:06) [4]
> воочию наблюдаешь строки для которых равенство или лайк
> не выполняется но в выборке они есть?
Да.
В результате получается набор, в котором записи, включающие хотя бы одно слово из таблицы слов.
-
Да.
В результате получается набор, в котором записи, включающие хотя бы одно слово из таблицы слов.
в результате получается выборка, во всех строках которой выполняются все условия что там у тебя понаписаны.
а что там ты подразумевал в уме промеж строк запроса - про то сервер не в курсе.
-
> rrrrr © (12.04.17 14:47) [7]
Мне нужно выбрать только те строки, которые содержат все слова , которые в таблице tmp_words.
Я написал рекурсивное СТЕ для этого.
В результате получается набор, в котором записи, включающие хотя бы одно слово из таблицы слов.
Что исправить , чтобы выбирались только записи со всеми словами таблицы слов?
-
Мне нужно выбрать только те строки, которые содержат все слова , которые в таблице tmp_words.
Я написал рекурсивное СТЕ для этого.
ну и где там в написанном программируется "только когда все слова" ?
в [5] - там оно есть.
находим объекты у которых нет хотя бы одного слова, затем выбираем все объекты которые "не такие"
а у тебя где?
-
> rrrrr © (12.04.17 15:03) [9]
То, что, как мне кажется, я написал:
В первой итерации для первого слова из tmp_words выбираем записи из таблицы objects, в которых поле Name содержит это слово.
В следующих итерациях Для выбранных в предыдущей записей ищем второе слово... и т.д.
from tmp_words t_w
inner join objects on (Upper(objects.name) like ('%' || upper(t_w.word_body) || '%'))
inner JOIN Check_Words cc_ww
ON
(
(t_w.word_num = CC_WW.NEXT_WORD_NUM ) and
(
objects_id = CC_WW.objects_id
)
)
Когда добрались до последнего слова, выводится результирующий набор.
-
я вижу лайк и равно.
и все что лайкает и равняется - всё попало в выборку.
и нет там никаких условий на "когда только лишь все слова"
и у сервера нет никаких "предыдущих" записей. он берет пару очередных кандидатов на джойн и сравнивает.
совпало - сует в выборку. не совпало - не сует.
зачем весь этот трэш и угар?
к чему там "некст ворд"?
важен порядок слов?
ну так юзай лайк и готовую маску "%мама%мыла%раму%"
порядок слов не важен?
юзай [5]
-
> rrrrr © (12.04.17 15:30) [11]
Я деревья высаживаю.
Там есть задачи на рекурсию.
Эту "задачку" разбираю для примера, чтобы понять, как работает рекурс.СТЕ
(t_w.word_num = CC_WW.NEXT_WORD_NUM ) - в эту выборку берётся следующее слово из предыдущей итерации.
and
objects_id = CC_WW.objects_id - и только те объекты, которые выбраны в предыдущей итерации(то есть, содержат предыдущие слова).
-
"руззьке языг сто балл, патступаю мгемо"
нет никаких "предыдущих" итераций.
они уже если сработали при сравнении "той итераци", то обжект ид уже в выборке есть.
и если "следующая" "итерация"не сработает,
то айдишник, который был добавлен "вчера" в "предыдущей итерации" - его уже никто из выборки не "выкинет".
-
его уже никто из выборки не "выкинет".
suspend: Когда добрались до последнего слова, выводится результирующий набор.
-
с точки зрения эволюции
было бы правильнее
если бы деревья высаживали тебя.
до них кажись уже дошло бы.
-
"Выполнение рекурсивного CTE с точки зрения сервера Firebird можно описать
следующим образом:
• Сервер начинает выполнение с не рекурсивного члена;
• Для каждой выбранной строки из нерекурсивного части выполняется каждый
рекурсивный член один за другим, используя текущие значения из предыдущей
итерации как параметры;
• Если во время выполнения экземпляр рекурсивного элемента не выдаёт строк, цикл
выполнения переходит на предыдущий уровень и получает следующую строку от
внешнего для него набора данных."
-
"Выполнение рекурсивного CTE с точки зрения сервера Firebird можно описать
следующим образом:
чувак, скажи мне
где там написано что если не выполнилось условие скажем только последней итерации, то вся выборка должна быть похерена?
-
вот тебе на пальцах:
две таблицы с одним полем name
мама мама
мыла мыла
раму папу
запрос:
select a.*
from a, b
where a.name = b.name
по твоей извращенной логике выборка должна быть пустой, потому что в "а" не все строки равны строкам "в"
-
По-моей логике:
0 - тебя
1 - деревья
11 если бы деревья высаживали тебя.
15 белый человек очень умный
22 если бы высаживали тебя баобабы .
первая итерация
0- тебя
набор 1
11 - 0
22 - 0
вторая
1 - деревья
11 - 1
результирующий:
ID WORD_NUM
11 - 0
22 - 0
11 - 1
For
Select * from результирующий
into
do
begin
if Word_Num = 1 then
suspend
end
11 - 1
11 если бы деревья высаживали тебя.
-
интересно зачем тебе firebird
вручную на бумажке так складно вся выборка расписана.
предлагаю выбросить сервер.
-
выброси
-
у меня все сервера возвращают ровно то о чем я их прошу.
а на бумажке у меня это медленно получается.
это ты выбрасывай.
это у тебя сервер "игнорирует" "требования".
я бы выбросил, если бы мой так делал.
но мой не делает так.
-
> rrrrr © (12.04.17 17:03) [22]
по-любому, спасибо.
-
Фб - это обязательно? Сфинкс не помог?
-
>rrrrr © (12.04.17 14:20) [5]
не нужно усложнять:
select *
from objects obj
where not exists...
-
там чтобы наглядно. по шагам.