powered by simpleCommunicator - 2.0.49     © 2025 Programmizd 02
Форумы / MySQL [игнор отключен] [закрыт для гостей] / SQL запрос - создать продвинутые группы. Помогите.
14 сообщений из 14, страница 1 из 1
SQL запрос - создать продвинутые группы. Помогите.
    #40058638
Добрый день. Помогите с запросом пожалуйста. Уже замучился изобретать.

Или хотя бы подскажите как такая задача/группировка называется.

Можно создавать VIEW и временные таблицы.
Можно несколькими запросами.
Нельзя триггеры/функции/хранимые процедуры.

Задача общая:
Есть таблица предложений (лингвистическое значение), состоящих из одного или более слов. Каждое слово имеет альтернативы (одну, себя же, или более).
Объединить предложения в группы, если пересекаются альтернативы каждого из слов.

Более детально:
Структура таблиц:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
sentences
 - id
 - title (varchar(191))

words
 - id
 - word (varchar(191))

alternatives
 - id
 - alternative (varchar(191))

sentence_word
 - id
 - sentence_id
 - word_id

alternative_word
 - id
 - word_id
 - alternative_id



Что должно быть на выходе:
примерно такой результат:
Код: sql
1.
2.
3.
4.
5.
6.
+------------------------------------------+
|GROUP_CONCAT(sentences.id)                |
+------------------------------------------+
|58,93,125,138,308,410,420,471,4008        |
|58,7677                                   |
+------------------------------------------+



Пример :
есть предложения:
He told me a story (id = 1)
They tell me a story (id = 2)
She told me a story yesterday (id = 3)

слово "He" имеет альтернативы "He", "She", "They". (каждое слово имеет альтернативу себя же)
слово "She" имеет альтернативы "She", "He", "They".
слово "They" имеет альтернативы "They", "She", "He".
слово "told" имеет альтернативы "tell", "told"
слово "tell" имеет альтернативы "told", "tell"
слово "me " имеет альтернативы "me"
слово "story" имеет альтернативы "story"
слово "yesterday" имеет альтернативы "yesterday"

Получется, предложение "He told me a story" путем замены альтернативами может быть преобразовано в "They tell me a story"
Абстрактно говоря, предложения 1 и 2 взяимо преобразуемые путем подстановки альтернатив их слов: "He/She/They told/tell me a story". В этом и есть цель. Объединить все такие предложения по группам.

Однако ни "He told me a story" ни "They tell me a story" не может быть преобразовано в "She told me a story yesterday" так как последнем есть слово "yesterday", альтернативы которого не встречаются у слов из других предложений.

То есть на выходе должны быть две группы:
Код: sql
1.
2.
3.
4.
5.
6.
+------------------------------------------+
|GROUP_CONCAT(sentences.id)                |
+------------------------------------------+
|1,2                                       |
|3                                         |
+------------------------------------------+



Мне кажется что это тривиальная задача для реляционной субд. С трудом верится что она так трудно решается.
Или хотя бы направьте меня в какое-то напрввление, что использовать.
...
Рейтинг: 0 / 0
SQL запрос - создать продвинутые группы. Помогите.
    #40058745
paver
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Дмитрий shinobisun, имхо очень нечеткие условия.

- "ни "He told me a story" ни "They tell me a story" не может быть преобразовано в "She told me a story yesterday" так как " в предложениях разное количество слов
- Может ли А иметь альтернативы Б и В, но Б и В не являться альтернативами между собой? Например:
слово "He" имеет альтернативы "He", "They".
слово "She" имеет альтернативы "She", "They".
слово "They" имеет альтернативы "They", "She", "He".
- Если второе условие недопустимо, как 58 может группироваться и с 93, и с 7677, а 93 с 7677 между собой не группируются?

Если разрешить только замкнутые группы альтернатив (если А <alt> Б и А <alt> В то Б <alt> В), то решение следующее:
1. В каждой группе альтернатив назначаем строго одну главную. В alternative_word оставляем только строки с главной альтернативой (пусть "They" - главная, тогда оставляем только:
"He", "They".
"She", "They".
"They", "They").
2. Все Предложения преобразуем в Предложения-штрих (в дополнительном поле title2), где все слова заменены на главные альтернативы
3. Тупо группируем по полю title2, в GROUP_CONCAT(sentences.id) получаем требуемый результат.
...
Рейтинг: 0 / 0
SQL запрос - создать продвинутые группы. Помогите.
    #40058746
paver
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Дмитрий shinobisun, не до конца вчитался в задачу.

Решение:
1. - оставляем
2. получаем временную таблицу sentence_word_tmp
- id
- sentence_id
- word_id_alt
где все word_id заменены на главные альтернативы
3. получаем временную таблицу sentence_tmp
- sentence_id
- sentence
где sentence - результат GROUP_CONCAT(word_id_alt) после группировки sentence_word_tmp по sentence_id
4. Группируем sentence_tmp по полю sentence, в GROUP_CONCAT(sentences.id) получаем требуемый результат.
...
Рейтинг: 0 / 0
SQL запрос - создать продвинутые группы. Помогите.
    #40058751
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вы бы выложили CREATE TABLE да INSERT INTO (5-10 строк на таблицу), а не бредовые описания таблиц... и соответственно результат для именно таких данных. Чисто для тестов.
...
Рейтинг: 0 / 0
SQL запрос - создать продвинутые группы. Помогите.
    #40058755
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да, кстати.

Чем и как гарантируется, что все данные полны (т.е., например, все слова предложения описаны в sentence_word, все альтернативы слова, включая его само, описаны в alternative_word, и т.п.)? или ничем, и формально половина соответствий может отсутствовать?

Слова в предложении - строго разделены одним пробелом? Или там двойные пробелы, запятые и прочая хрень - обычное дело? Начальных и хвостовых пробелов - точно нет?

Почему таблица sentence_word не содержит поле местоположения? Если в предложении слово встречается дважды - сколько записей для него в таблице sentence_word?

Какая точно версия MySQL?

Должно ли учитываться количество слов в предложении? например, "A B C D" и "A B C A D" - это группа?

Должен ли учитываться порядок слов в предложении? например, "A B C D" и "A C B D" - это группа?

PS. fiddle с отфонарными данными для экспериментов.
...
Рейтинг: 0 / 0
SQL запрос - создать продвинутые группы. Помогите.
    #40058850
paver
Дмитрий shinobisun, имхо очень нечеткие условия.
Если разрешить только замкнутые группы альтернатив (если А <alt> Б и А <alt> В то Б <alt> В), то решение следующее:
1. В каждой группе альтернатив назначаем строго одну главную. В alternative_word оставляем только строки с главной альтернативой (пусть "They" - главная, тогда оставляем только:
"He", "They".
"She", "They".
"They", "They").
2. Все Предложения преобразуем в Предложения-штрих (в дополнительном поле title2), где все слова заменены на главные альтернативы
3. Тупо группируем по полю title2, в GROUP_CONCAT(sentences.id) получаем требуемый результат.


Да, разрешить только замкнутые группы.
Получение главной альтернативы не подходит. Я так делал, при такой ситуации связь многие ко многим для слов и альтернатив становится избыточной. Достаточно добавить новый столбец в sentences, в котором хранить предложение щаписанное главными альтернативами для слов. Этот вариант не подходит.

Вот создал: https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=a84f1b2a61dd4d130eb9855675079a60
...
Рейтинг: 0 / 0
SQL запрос - создать продвинутые группы. Помогите.
    #40058868
paver
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Дмитрий shinobisun

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

Не понял, почему не подходит.
Например, у вас есть предложение "Предложение", состоящее из слов П, р, е, д, и т.д. с альтернативами П-п, р-Р, е-Е, д-Д и т.д. Если вам нужно сравнить несколько предложений, например, "Предложение", "ПРедложение" и "ПРЕдложение", вы просто приводите их все к одному регистру (главной альтернативе - "ПРЕДЛОЖЕНИЕ"), а затем сравниваете (группируете).
...
Рейтинг: 0 / 0
SQL запрос - создать продвинутые группы. Помогите.
    #40058889
paver
Дмитрий shinobisun

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

Не понял, почему не подходит.
Например, у вас есть предложение "Предложение", состоящее из слов П, р, е, д, и т.д. с альтернативами П-п, р-Р, е-Е, д-Д и т.д. Если вам нужно сравнить несколько предложений, например, "Предложение", "ПРедложение" и "ПРЕдложение", вы просто приводите их все к одному регистру (главной альтернативе - "ПРЕДЛОЖЕНИЕ"), а затем сравниваете (группируете).


Проблема в том, что нет строгого сопоставления альтернатив. "П" - может иметь альтернативы "п", "П". А например, "P" латинсоке, кроме себя же, может иметь альтернативой только "п", но не "П". А "Х", только "П".
И альтернатив не всегда по две. Их может быть три, пять, десять.
...
Рейтинг: 0 / 0
SQL запрос - создать продвинутые группы. Помогите.
    #40058909
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий shinobisun
Проблема в том, что нет строгого сопоставления альтернатив. "П" - может иметь альтернативы "п", "П". А например, "P" латинсоке, кроме себя же, может иметь альтернативой только "п", но не "П". А "Х", только "П".

Это получается, что предложение А может быть эквивалентно Б, которое эквивалентно В, но А при этом неэквивалентно В. Ну или А и Б по отдельности эквивалентны В, но не эквивалентны друг другу. И как при такой хрени ты собираешься формировать группы?
...
Рейтинг: 0 / 0
SQL запрос - создать продвинутые группы. Помогите.
    #40058911
Akina
Дмитрий shinobisun
Проблема в том, что нет строгого сопоставления альтернатив. "П" - может иметь альтернативы "п", "П". А например, "P" латинсоке, кроме себя же, может иметь альтернативой только "п", но не "П". А "Х", только "П".

Это получается, что предложение А может быть эквивалентно Б, которое эквивалентно В, но А при этом неэквивалентно В. Ну или А и Б по отдельности эквивалентны В, но не эквивалентны друг другу. И как при такой хрени ты собираешься формировать группы?


Всё верно. Так и получается.

И так, задача не решает с помощью SQL?
...
Рейтинг: 0 / 0
SQL запрос - создать продвинутые группы. Помогите.
    #40058958
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну как может решаться задача, которая не имеет решения? Вернее, любое решение которой противоречит части условий задачи?
...
Рейтинг: 0 / 0
SQL запрос - создать продвинутые группы. Помогите.
    #40058988
Gluck99
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Задача чем-то похожа на отбор автозапчастей по связке "оригинальный номер запчасти" - "неоригинал". Но там связь устанавливается четко независимо от такой сущности как "предложение" (её там просто нет). В вашей задаче, если я правильно понял, возникает ситуация, когда набор альтернатив меняется в зависимости от конкретных предложений (что логично). Проблема в том, что эти зависимости невозможно указать заранее.

Что делать, если появляется предложение №4 "Father told me a story"? По структуре оно аналогично предложениям 1 и 2, т.е. "father" является аналогом для "he", "she" and so on. Т.е. тут может быть практически любое существительное или местоимение в качестве подлежащего. Как быть с расширением количества таких предложений?

Вам нужна объединяющая сущность - группа предложений, исключительно в рамках которой существуют наборы альтернатив. Но если у вас как раз обратная задача - найти такие группы, то я х.з. как это сделать.

Если вы считаете, что решение есть, попробуйте его описать не в привязке к SQL, а просто алгоритмически, на абстрактном языке.
...
Рейтинг: 0 / 0
SQL запрос - создать продвинутые группы. Помогите.
    #40059113
Не в привязке к SQL это решается циклами.

Пример с этими данными: https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=a84f1b2a61dd4d130eb9855675079a60

Получаем из БД группы:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
SELECT sub1.sentence_id,
       CONCAT("[", GROUP_CONCAT(DISTINCT sub1.alternative_LIST), "]") as alternative_groups
FROM (
         SELECT sub0.sentence_id,
                CONCAT("[", GROUP_CONCAT(DISTINCT sub0.alternative_id), "]") as alternative_LIST
         FROM (
                  SELECT s.id AS sentence_id,
                         w.id AS word_ID,
                         a.id AS alternative_id
                  FROM sentences s
                           JOIN sentence_word sw ON s.id = sw.sentence_id
                           JOIN words w ON sw.word_id = w.id
                           JOIN alternative_word aw ON w.id = aw.word_id
                           JOIN alternatives a ON aw.alternative_id = a.id
              ) AS sub0
         GROUP BY sub0.sentence_id, sub0.word_ID
         ORDER BY sub0.sentence_id, sub0.word_ID
     ) as sub1
GROUP BY sub1.sentence_id



Результат:
Код: php
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.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
array (
  0 => 
  stdClass::__set_state(array(
     'sentence_id' => 1,
     'alternative_groups' => '[[1,2],[3,4,5],[6,7,11]]',
  )),
  1 => 
  stdClass::__set_state(array(
     'sentence_id' => 2,
     'alternative_groups' => '[[1,2],[3,4,5],[6,7,11]]',
  )),
  2 => 
  stdClass::__set_state(array(
     'sentence_id' => 3,
     'alternative_groups' => '[[10,15],[8,9]]',
  )),
  3 => 
  stdClass::__set_state(array(
     'sentence_id' => 4,
     'alternative_groups' => '[[10,15],[8,9]]',
  )),
  4 => 
  stdClass::__set_state(array(
     'sentence_id' => 5,
     'alternative_groups' => '[[1,2],[12,13],[3,4,5],[6,7,11]]',
  )),
  5 => 
  stdClass::__set_state(array(
     'sentence_id' => 6,
     'alternative_groups' => '[[1,2],[12,13],[3,4,5],[6,7,11]]',
  )),
  6 => 
  stdClass::__set_state(array(
     'sentence_id' => 7,
     'alternative_groups' => '[[14],[3,4,5],[6,7,11]]',
  )),
)



Нормализованный массив будет таким:
Код: php
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.
26.
27.
28.
29.
30.
$result = [
            [
                'sentence_id' => 1,
                'alternative_groups' => [[1, 2], [3, 4, 5], [6, 7, 11]]
            ],
            [
                'sentence_id' => 2,
                'alternative_groups' => [[1, 2], [3, 4, 5], [6, 7, 11]],
            ],
            [
                'sentence_id' => 3,
                'alternative_groups' => [[10, 15], [8, 9]],
            ],
            [
                'sentence_id' => 4,
                'alternative_groups' => [[10, 15], [8, 9]],
                ],
            [
                'sentence_id' => 5,
                'alternative_groups' => [[1, 2], [12, 13], [3, 4, 5], [6, 7, 11]],
            ], 
            [
                'sentence_id' => 6,
                'alternative_groups' => [[1, 2], [12, 13], [3, 4, 5], [6, 7, 11]],
            ],
            [
                'sentence_id' => 7,
                'alternative_groups' => [[14], [3, 4, 5], [6, 7, 11]]
            ],
            ];



далее так, код на PHP:
Код: php
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.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
 while(count($result) > 0) { // обходим пока не кончится

            $mainItem = array_shift($result); // извлекаем элемент из начала

            $tmpRes = []; // создаем временный массив
            $tmpRes[] = $mainItem['sentence_id']; // добавляем ID предлоажения, как первого в наборе. Оно будет либо одно, либо если найдутся пересекающиеся, добавим и другие ID

            foreach ($result as $secondaryItem) { // берем каждый элемент из оставшегося набора результатов

                $allGroupsIntersect = true; // ключ, говорящий о том, что все слов из главного набора, имет пересечения по альтернативам со словами из текущего элемента взятого из оставшихся групп

                // ниже сравнение, пересекаются ли все группы альтернатив. По сути пересекаются ли слова путем подcтавновки альтернатив
                foreach ($secondaryItem['alternative_groups'] as $secondaryAlternativeGroup) {

                    $groupIntersects = false;
                    foreach ($mainItem['alternative_groups'] as $mainAlternativeGroup) {

                        if (array_intersect($mainAlternativeGroup, $secondaryAlternativeGroup)) {
                            $groupIntersects = true;
                        }
                    }

                    if (!$groupIntersects) {
                        $allGroupsIntersect = false;
                        break 1;
                    }
                }

                if ($allGroupsIntersect) { // если все группы пересекаются, предложения подходящие
                    $tmpRes[] = $secondaryItem['sentence_id']; // добавляем ID предложения во временный результат
                }

            }

            $merged[] = $tmpRes; // добавляем временный результат в общий результат
        }



Рузультат:
Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
$merged = [
            [1,2],
            [2],
            [3,4],
            [4],
            [5,6],
            [6],
            [7]
        ];



Осталось объединить пересекающиеся группы, и всё. Но в целом результат достигнут.

Минус один -при количестве записей sentences ~20000, скрипт выполняется около 15 минут.

Если средствами только SQL это решить нельзя. Тогда циклами можно считать задачу решенной.
...
Рейтинг: 0 / 0
SQL запрос - создать продвинутые группы. Помогите.
    #40062093
...
Рейтинг: 0 / 0
14 сообщений из 14, страница 1 из 1
Форумы / MySQL [игнор отключен] [закрыт для гостей] / SQL запрос - создать продвинутые группы. Помогите.
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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