#mysql #sql #select #mysql-5.7
#mysql — сервер #sql #выберите #mysql-5.7 #mysql
Вопрос:
У меня есть таблица
и я пытаюсь написать select
оператор с ifnull
условием для того же type
значения, чтобы получить результат, как показано в этой таблице
Ниже приведен 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. Добавлены соответствующие теги версии. Спасибо за ответ! 🙂