#mysql #sql
#mysql #sql
Вопрос:
Я пытаюсь группировать строки на основе других столбцов.
Вот как выглядит таблица:
| a_id | a_name | b_id | b_name | c_id | c_name | d_id | d_name |
|------|--------|------|--------|------|--------|------|--------|
| 1 | abcdef | 0 | | 0 | | 0 | |
| 2 | zxy | 0 | | 0 | | 0 | |
| 3 | lmao | 0 | | 0 | | 0 | |
| 0 | | 1 | oop | 0 | | 0 | |
| 0 | | 2 | abcdef | 0 | | 0 | |
| 0 | | 0 | | 1 | nope | 0 | |
| 0 | | 0 | | 2 | nothing| 0 | |
| 0 | | 0 | | 0 | | 1 | abcdef |
| 0 | | 0 | | 0 | | 2 | oop |
| 0 | | 0 | | 0 | | 3 | turtles|
Я хочу, чтобы все похожие имена были объединены в одну строку. Сходство определяется определяемой пользователем функцией IS_SAME(str1, str2).
Вот как должен выглядеть результат.
| a_id | a_name | b_id | b_name | c_id | c_name | d_id | d_name |
|------|--------|------|--------|------|--------|------|--------|
| 1 | abcdef | 2 | abcdef | 0 | | 1 | abcdef |
| 2 | zxy | 0 | | 0 | | 0 | |
| 3 | lmao | 0 | | 0 | | 0 | |
| 0 | | 1 | oop | 0 | | 2 | oop |
| 0 | | 0 | | 1 | nope | 0 | |
| 0 | | 0 | | 2 | nothing| 0 | |
| 0 | | 0 | | 0 | | 3 | turtles|
На самом деле я создал запрос для этого, но я использовал всю последнюю теорему Ферма и не сохранил используемый мной запрос (я сохранил предыдущие 5 запросов, которые я использовал для ведения этого списка), потому что я чувствовал, что это слишком просто для записи.
Комментарии:
1. Разрешено ли нам предлагать нормализацию?
Ответ №1:
Это сложно, но выполнимо. Вы хотите начать со списка имен, а затем объединить в каждой таблице и объединить в первом столбце:
select max(ta.a_id) as a_id, max(ta.a_name) as a_name,
max(tb.b_id) as a_id, max(tb.b_name) as b_name,
max(tc.c_id) as a_id, max(tc.c_name) as c_name,
max(td.d_id) as a_id, max(td.d_name) as d_name
from (select a_name as name from table t union select b_name union select c_name union select d_name
) names left outer join
table ta
on is_same(ta.a_name, names.name) left outer join
table tb
on is_same(tb.b_name, names.name) left outer join
table tc
on is_same(tc.c_name, names.name) left outer join
table td
on is_same(td.d_name, names.name)
group by names.name;
Комментарии:
1. Как я могу использовать свою функцию IS_SAME() для сравнения вместо того, чтобы создавать группу, которая предполагает 100% сходство?
2. @Nikzilla . , , Это то, что делает этот запрос.
3. Ох. Что ж, в таком случае я проверю это! Не кодируйте, когда устали!
4. если
group by names.name
могут быть повторяющиеся строки из-за разных имен сis_same(..) = true
. возможно, потребуется дедуплицировать результат.5. @Fabricator . , , В вашем вопросе, похоже, нет примеров таких дубликатов. В любом случае,
group by
дубликаты удаляются и выбирается одно из значений. Вы можете использоватьgroup_concat()
для получения всех значений в столбце.