За последние 24 часа нас посетили 22594 программиста и 1201 робот. Сейчас ищут 764 программиста ...

Скопировать уникальные из 2х колонок

Тема в разделе "MySQL", создана пользователем Interpreter, 20 июл 2019.

  1. Interpreter

    Interpreter Активный пользователь

    С нами с:
    29 ноя 2013
    Сообщения:
    25
    Симпатии:
    0
    Здравствуйте.
    Прошу помочь. Требуется скопировать одну таблицу, состоящую из 2х полей в другую таблицу из 2х полей, учитывая, что копировать нужно только уникальные записи, а критерий уникальности таков:
    1)Миша-Женя не уникальный(т.к. есть Женя-Миша(см. ниже))
    2)Женя-Миша (не уникальный, т.к. есть Миша-Женя (см. выше))
    3)Миша-Миша (и любые другие дубли) тоже должно быть удалено
    Как это сделать многоходовкой с помощью промежуточной(ных)таблиц(ы)я примерно понимаю, но может, есть изящный подход буквально в несколько команд (я не очень разбираюсь: не программист). Особенно буду признателен, если в качестве факторов будет учтено, что кол-во строк около 50 000 000, а хостинг бесплатный (соответственно, время выполнения команд, вероятно, ограничено).
    Заранее благодарю!
     
  2. Valick

    Valick Активный пользователь

    С нами с:
    12 авг 2018
    Сообщения:
    1.911
    Симпатии:
    328
    На заре на столе
    Разноцветны стёклышки
    Разноцветны тряпочки-
    Непонятно ни хрена
     
    Interpreter и Неугомонный нравится это.
  3. Interpreter

    Interpreter Активный пользователь

    С нами с:
    29 ноя 2013
    Сообщения:
    25
    Симпатии:
    0
    А рубаи прикольные )) Вроде пояснил как мог. Если вкратце, то надо очистить таблицу, состоящую из 2 полей от записей:
    1 2 (т.к. это обратный дубль к следующей записи)
    2 1 (т.к. это обратный дубль к предыдущей записи)
    1 1 (в обоих полях одинаковые значения)
    2 2 (в обоих полях одинаковые значения)
     
  4. Valick

    Valick Активный пользователь

    С нами с:
    12 авг 2018
    Сообщения:
    1.911
    Симпатии:
    328
  5. Interpreter

    Interpreter Активный пользователь

    С нами с:
    29 ноя 2013
    Сообщения:
    25
    Симпатии:
    0
    id int(11) auto_increment
    number1 varchar(20)
    number2 varchar(20)
     
  6. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.076
    Симпатии:
    1.237
    Адрес:
    там-сям
    Я правильно понимаю, если есть "повторы", то надо удалить все такие записи, не оставляя уникальной?

    Было
    1,2
    2,1
    4,5
    Стало
    4,5

    Какая-то ерунда, по-моему :)
    --- Добавлено ---
    Это похоже на неправильную интерпретацию тестового задания с собеседования.
    --- Добавлено ---
    Ну если это таки правильная постановка, то можно сделать так:

    Код (SQL):
    1. SELECT least(x,y), greatest(x,y)
    2. FROM ttt
    3. WHERE x<>y
    4. GROUP BY 1,2
    5. HAVING COUNT(*)=1
    --- Добавлено ---
    А чтобы скопировать в новую таблицу, надо использовать insert...select
     
  7. Interpreter

    Interpreter Активный пользователь

    С нами с:
    29 ноя 2013
    Сообщения:
    25
    Симпатии:
    0
    Нет, не так. Простите, действительно это я так описал. Надо так:
    Было
    1,1
    1,2
    2,1
    4,5
    Стало
    1,2
    4,5
    и там будут не цифры, а текст (что-то типа 7L0129620), название таблицы cross
     
  8. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.076
    Симпатии:
    1.237
    Адрес:
    там-сям
    Для SQL без разницы что группировать: цифры или что-то другое.
    Если надо таки оставить уникальные значения, то уберите фразу having из моего запроса.
    Как вариант, можно переделать с группировки на distinct. Суть та же, но немного короче.

    Select distinct least(x,y), greatest(x,y)
    From ttt
    Where x<>y
     
  9. Interpreter

    Interpreter Активный пользователь

    С нами с:
    29 ноя 2013
    Сообщения:
    25
    Симпатии:
    0
    Спасибо большое, работают оба варианта!
    Только вот мне надо выходные данные либо в новую таблицу залить либо эту же таблицу заменить выходными данными. Пробую залить в новую вот так:
    Код (Text):
    1. INSERT INTO 'cross' SELECT distinct least(number1,number2), greatest(number1,number2) FROM `temp` WHERE number1<>number2
    но не работает :( Подскажите, пожалуйста, решение.
     
  10. Valick

    Valick Активный пользователь

    С нами с:
    12 авг 2018
    Сообщения:
    1.911
    Симпатии:
    328
    @Interpreter, достаточно сходить в мануал и почитать какие условия нужны для insert ... select.
    Названия полей принимающей таблицы должны совпадать с названиями полей таблицы выборки. Для этого надо сделать alias для least и greatest. Погугли, что такое AS в MySQL.
     
  11. Interpreter

    Interpreter Активный пользователь

    С нами с:
    29 ноя 2013
    Сообщения:
    25
    Симпатии:
    0
    Погуглил... про AS отдельно написано, про least и greatest - написано, а вот про их связку особо ничего. Только на одном каком-то сайте нашел нечто похожее, в результате чего составил какую-то вот такую "дичь":
    Код (Text):
    1. INSERT INTO 'cross' ('number1', 'number2')
    2. SELECT distinct least(number1,number2) AS least_value
    3. greatest(number1,number2) AS greatest_value
    4. FROM `temp` WHERE number1<>number2
    которая все равно не работает. Прошу помощи.
     
  12. Valick

    Valick Активный пользователь

    С нами с:
    12 авг 2018
    Сообщения:
    1.911
    Симпатии:
    328
    В таблице cross какие поля?
    P.S. сорь не то подсказываю, вечером продолжим.
     
  13. Interpreter

    Interpreter Активный пользователь

    С нами с:
    29 ноя 2013
    Сообщения:
    25
    Симпатии:
    0
    В таблице cross поля: id int(11) auto_increment | number1 varchar(20) | number2 varchar(20)
    В таблице temp поля: number1 varchar(20) | number2 varchar(20)
     
  14. Interpreter

    Interpreter Активный пользователь

    С нами с:
    29 ноя 2013
    Сообщения:
    25
    Симпатии:
    0
    Все получилось:
    Код (Text):
    1. INSERT INTO `cross` (`number1`, `number2`)
    2. SELECT distinct least(`number1`, `number2`),
    3. greatest(`number1`, `number2`)
    4. FROM `temp` WHERE number1<>number2
    Спасибо огромное всем за помощь!
     
  15. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.076
    Симпатии:
    1.237
    Адрес:
    там-сям
    Для спасибо есть кнопка с большим пальцем вверх - мы здесь за лайки работаем ;)
     
    Interpreter и Taktreba нравится это.