Выберите, если строка содержит подстроку только один раз - PullRequest
0 голосов
/ 28 декабря 2018

Я пытаюсь создать отчет, который извлекает данные между двумя датами, и где строка встречается только один раз в столбце описания, который имеет тип данных text

Я пытался использовать решение из "postgresql"-select-if-string-содержит "stackoverflow вопрос, но он не учитывал количество повторений строки в блоке описания.

SELECT o.ownername, to_char(a.auditdate, 'MM/DD/YYYY') as dateday, 
o.additionalflags, 
o.emailaddress, o.id, a.description, a.username, 
CASE WHEN a.Action = 0 THEN 'ADD'
WHEN a.Action = 1 THEN 'EDIT'
WHEN a.Action = 2 THEN 'DELETE'
WHEN a.Action = 3 THEN 'MOVE'
WHEN a.Action = 4 THEN 'LOGIN'
WHEN a.Action = 5 THEN 'LOGOUT'
END AS Action
FROM owner o
INNER JOIN audittrail a ON o.id = a.linkid
/*
WHERE array_length(regexp_matches(description, '1\-Gets Email'), 1) = 1
*/
AND a.auditdate >= '$ASK DATE Enter the from date$' 
AND a.auditdate <= '$ASK DATE Enter the to date$'
ORDER BY o.ownername

Столбец, который я пытаюсь просеятьимеет данные, которые выглядят так:

(ID 2) >>> LASTCHANGEDDATE: 2011-11-11 11:11:11.653868 ==> 2018-12-23 14:24:28.694724, ADDITIONALFLAGS: *1-Atest|1-Gets Email|1-Gets Snail Mail|Adopter-|donor|driver|fosterer|homechecked|homechecker|member|V-Foster Home: short-term/emergency|* ==> **1-Gets Email|1-Gets Snail Mail|Adopter-NCGSPR Dog|donor|driver|fosterer|homechecked|homechecker|member|V-Foster Home: short-term/|volunteer|,**

Столбец в значительной степени представляет собой журнал описания того, что изменилось в базе данных.Выделенные курсивом слова - это то, что ДОПОЛНИТЕЛЬНЫЕ ФЛАГИ являются прошлым, а жирные слова - это новые и текущие ДОПОЛНИТЕЛЬНЫЕ ФЛАГИ после изменения.Я ищу строки с описанием «1-Gets Email» один раз, потому что меня интересуют только те, которые изменились, а не те, у которых «1-Gets Email» до дат, которые я запросил.

Ответы [ 2 ]

0 голосов
/ 29 декабря 2018

split_part() может быть использовано для простого и быстрого решения:

...
WHERE  description ~ '1-Gets Email'
AND    split_part(description, '1-Gets Email', 3) = '';

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

Если таблица большая, вы можете добавить индекс триграммы для поддержки первого предложения WHERE (description ~ 'pattern') и сделать его много Быстрее.Например:

CREATE INDEX tbl_description_gin_trgm_idx ON tbl USING gin (description gin_trgm_ops);

См .:

0 голосов
/ 28 декабря 2018

Довольно странно, но должно работать: проверьте, равна ли длина описания минус длина искомого текста длине описания, где искомый текст заменяется пустой строкой.

...
WHERE length(description) - length('1-Gets Email') = length(replace(description, '1-Gets Email', ''))
...

Или более общий подход: проверьте количество найденных совпадений regexp_matches(), в данном случае 1.

...
WHERE (SELECT count(*)
              FROM regexp_matches(description, '1\-Gets Email', 'g')) = 1
...
...