sql подстрока содержит - PullRequest
       4

sql подстрока содержит

0 голосов
/ 24 сентября 2019

У меня есть набор данныхA с длинным повествовательным полем.Это поле называется «повествование».

У меня есть набор данныхB, полный терминов животных, таких как «собака», «кошка», «мышь».Это поле называется «животные».

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

Например, если в повествовании найдено слово «собака», поле animal_found для этой записи заполнит слова «собака»

, если найдены слова «собака» и «кошка», поле animal_found будет показывать "собака, кошка"

Любая мысль о том, как закодировать это в SQL?

Ответы [ 4 ]

0 голосов
/ 25 сентября 2019

SAS SQL - неправильный инструмент для объединения строк в результат конкатенации (строка csv).

SQL можно использовать для получения найденных элементов, которые нужно объединить, и цикла данных DOW для конкатенации:

proc sql;
  create view matched_animals as 
  select narrative, animal from
  narratives left join animals on narrative contains trim(animal)
  order by narratives, animal;

data want;
  length animal_found $2000;
  do until (last.narrative);
    set matched_animals;
    by narrative;
    animal_found = catx(',',animal_found,animal);
  end;
run;

Это будет работать, но может не хватать ресурсов в зависимости от количества элементов таблиц описаний и животных и скорости сопоставления.

В подходе с шагом данных можно использовать хеш-объект, countw и scan или findw.Есть два подхода, с way2 вероятным лучшим / наиболее типичным вариантом использования.

* Thanks Reeza for sample data;
data narratives;
infile cards;
input narrative $100.;
cards;
This is some random text with words that are weirhd such as cat, dog frogs, and any other weird names
This is a notehr rnaodm text with word ssuch as bird and cat
This has nothing in it
This is another phrages with elephants
;
run;

data animals;
input animal $20.;
cards;
cat
dog
frog
bird
elephant
;;;;
run;

data want;
  set narratives;

  length animals_found_way1 animals_found_way2 $2000;

  if _n_ = 1 then do;
    if 0 then set animals(keep=animal); * prep pdv;
    declare hash animals(dataset:'animals');
    animals.defineKey('animal');
    animals.defineDone();
    declare hiter animals_iter('animals');
  end;

  * check each word of narrative for animal match;
  * way 1 use case: narratives shorter than animals list;
  do _n_ = 1 to countw(narrative);
    token = scan(narrative, _n_);
    if animals.find(key:token) = 0 then 
      animals_found_way1 = catx(',', animals_found_way1, token);

    loopcount_way1 = sum (loopcount_way1, 1);
  end;

  * check each animal for match;
  * way 2 use case: animal list shorter than narratives;

  do while (animals_iter.next() = 0);
    if findw(narrative, trim(animal)) then 
      animals_found_way2 = catx(',', animals_found_way2, animal);

    loopcount_way2 = sum(loopcount_way2, 1);
  end;  

  put;

  drop token animal;
run;
0 голосов
/ 24 сентября 2019

Если список животных не слишком длинный, попробуйте этот метод и посмотрите, как он работает.Я проверял это на SQL Server 2017.

with 
cte1 as
(select 'I have a dog, a cat and a bunny as my pets' narrative union all 
select 'I have a horse, a bunny and a dog as my pets' union all 
select 'I have a cat as my pet' union all 
select 'I have a dog as my pet' union all
select 'I have nothing')

,cte2 as
(select 'cat'  animals union all 
select 'dog' union all 
select 'parrot' union all 
select 'bunny' union all 
select 'horse')

select 
narrative, 
string_agg(case when narrative like concat('%',animals,'%') then animals end,',') animals_found 
from cte1 cross join cte2
group by narrative;

Fiddle

0 голосов
/ 24 сентября 2019

Не SQL, но на шаге данных это можно сделать относительно легко.

  1. загрузка данных поиска во временный массив
  2. Цикл по списку и поиск текста для данных
  3. Объединение результатов при цикле

ПРИМЕЧАНИЕ: Это не обрабатывает дополнительные 's' в конце слов, поэтому вы можете подумать, как вы будете обращаться с лягушкой против лягушек, поскольку это технически не одно и то же слово.Вы не можете просто переключиться на поиск из-за частичных совпадений другими словами, но вы можете дважды продублировать цикл или изменить НАЙТИ, чтобы проверять оба в одно и то же время.Я оставлю это вам решать.

    *fake text data;
    data statements;
    infile cards;
    input narrative $100.;
    cards;
    This is some random text with words that are weirhd such as cat, dog frogs, and any other weird names
    This is a notehr rnaodm text with word ssuch as bird and cat
    This has nothing in it
    This is another phrages with elephants
    ;
    run;

    *fake words;
    data words;
    input word $20.;
    cards;
    cat
    dog
    frog
    bird
    elephant
    ;;;;
    run;



    *lookup;
    data want;

    *loads data set M into temporary array M;
    array W(5) $20. _temporary_;
        if _n_=1 then do j=1 to 5;
        set words;
       W(j)=word;
    end;

    *main data set to work with;

    length found $100.;
    found = '';
    set statements;
    do i=1 to dim(w);
    x = findw(narrative, W(i), " ,", 'ir');
    if  x > 0 then found = catx(", ", trim(found), w(i));
    *for debugging, comment out/delete as needed;
        put "N=" _N_ " | I= " i;
        put "Statement = " narrative;
        put "Word = " w(i);
        put "Found = " x;
        put "---------------";
    end;

    run;
0 голосов
/ 24 сентября 2019

Если вы используете SQL Server, есть способ с динамическим SQL, но он не очень элегантен и не эффективен.

DECLARE @Animal nvarchar(100)

DECLARE cur CURSOR LOCAL FORWARD_ONLY FOR
SELECT Animal FROM datasetB

OPEN cur

FETCH NEXT FROM cur INTO @Animal
WHILE @@FETCH_STATUS = 0
BEGIN
  DECLARE @Query NVARCHAR(MAX)
  SELECT @Query = 'SELECT Columns FROM datasetA where narrative like ''%' + @Animal + '%'''
  exec sp_executeSql @Query

  FETCH NEXT FROM cur INTO @Animal
  END

  CLOSE cur
  DEALLOCATE cur  

Способ сделать это, вероятно, будет создать временную таблицу или что-то вродеэто.Затем вставьте результаты в временную таблицу и отформатируйте ее так, как вы хотите.Но, как я уже сказал, курсоры не очень эффективны.Но это работает

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...