Условный запрос выбора, если значение в coulmn пустое

#mysql #sql #select #mysql-5.7

#mysql — сервер #sql #выберите #mysql-5.7 #mysql

Вопрос:

У меня есть таблица

1

и я пытаюсь написать select оператор с ifnull условием для того же type значения, чтобы получить результат, как показано в этой таблице

2

Ниже приведен sql, который я пробовал —

ВЫБЕРИТЕ тип, памятку, IFNULL(памятка, тип = type) memo_all, количество Из таблицы

Но я получаю тот же результат, что и memo столбец в memo_all столбце с приведенным выше запросом, как видно из этой таблицы 3. Пожалуйста, найдите здесь sqlfiddle с приведенным выше запросом и таблицей — http://sqlfiddle.com /#!9/55c43f

Чего мне здесь не хватает? Есть ли какой-либо альтернативный способ получить результат, как показано в таблице 2?

Комментарии:

1. Ваш образец данных содержит пары строк с одинаковыми type и разными memo значениями, где одна из них не является пустой строкой. Является ли оно (только одно непустое значение memo для каждого типа) абсолютным?

2. Я пытаюсь написать оператор выбора с условием ifnull Ваш образец скрипки содержит пустые строки '' . IFNULL() не проверяет их.

3. Да, оно является абсолютным. Вы правы. В моей таблице есть пустые строки.

Ответ №1:

На всякий случай, если вы используете версию MySQL более ранней, чем 8 , вот альтернатива ответу Гордона, который не использует оконные функции:

 SELECT
    t1.type,
    t1.memo,
    t2.memo AS memo_all,
    t1.amount
FROM yourTable t1
INNER JOIN
(
    SELECT type, MAX(memo) AS memo
    FROM yourTable
    GROUP BY type
) t2
    ON t1.type = t2.type;
  

Комментарии:

1. Да, я использую MySQL 5.7, и ответ Гордона не работает. Было бы здорово, если бы был способ получить это без t2 . Некоторые обходные пути для оконных функций MySQL 8 .

2. @yogi Смотрите последнюю правку Гордона, но обратите внимание, что даже там вам все равно нужно использовать подзапрос. Версия, которую я привел выше, может превосходить параметр коррелированного подзапроса.

3. Спасибо за ответ! 🙂

Ответ №2:

 SELECT t1.*, t2.memo memo_all
FROM `table` t1
JOIN `table` t2 USING (type)
WHERE t2.memo != '';
  

Решение, которое использует одну копию исходной таблицы:

 SELECT `table`.*, @tmp := CASE WHEN memo = '' THEN @tmp ELSE memo END memo_all
FROM `table`, (SELECT @tmp := '') variable
ORDER BY type, memo DESC;
  

Комментарии:

1. Спасибо вам за это. Это работает, но есть ли способ сделать это без создания временной таблицы t2 ?

2. @yogi??? где вы можете найти какую-либо временную таблицу? Я использую 2 копии исходной таблицы — и это не экзотика. Более того, я не могу представить метод, который позволяет решить задачу в вашей версии MySQL без использования 2 копий исходной таблицы, за исключением использования определяемой пользователем переменной. Смотрите другие 2 ответа для вашей серверной версии, оба также используют 2 копии исходной таблицы.

3. добавлено решение @yogi, которое использует одну копию исходной таблицы и пользовательскую переменную. Помните — это полное сканирование.

4. Извините, я сослался на 2-ю копию исходной таблицы как на временную таблицу. Никаких проблем с тех пор, как это сработало. Спасибо! 🙂

Ответ №3:

Используйте оконные функции:

 SELECT type, memo,
       max(memo) over (partition by type) as memo_all
       amount
FROM table;
  

Вы хотите «позаимствовать» значение из другой строки. Простая скалярная функция этого не сделает. Однако оконные функции предоставляют эту возможность.

Редактировать:

В более старых версиях MySQL вы можете использовать коррелированный подзапрос:

 SELECT type, memo,
       COALESCE(memo,
                (SELECT t2.memo
                 FROM table t2
                 WHERE t2.type = t.type AND t2.memo IS NOT NULL
                 LIMIT 1
                )
               ) as memo_all
       amount
FROM table t;
  

Комментарии:

1. Спасибо. Это сработало на скрипке, но у меня более низкая версия MySQL:(

2. @yogi . . . Я отредактировал ответ. Вы должны предоставить такую информацию в вопросе, используя теги, например.

3. Добавлены соответствующие теги версии. Спасибо за ответ! 🙂