Получить определенное значение в группе по оператору

У меня есть следующие три строки данных:

id       price          type
1        19.99          PERM
1        30.13          TEMP
2        14.44          SOME

Я хотел бы сгруппировать по id и получить цену, а цена TEMP всегда существует, используйте ее по умолчанию. Вот пример того, что должно быть на выходе:

id        price
1         30.13
2         14.44

Пока я застрял на group by:

SELECT 
GROUP_CONCAT(tp.price_value order by tp.price_type='temp' desc limit 1)
FROM prices GROUP BY id

Как бы я отдал приоритет цене (order by, limit 1) выше?

Теперь у меня две идеи: сделать два запроса (объединение кажется излишним?!) или постобработать group_concat на языке программирования. Ни то, ни другое не кажется слишком желательным, поэтому, надеюсь, здесь есть лучший и более простой подход.

используйте type='temp'

saravanatn 24.04.2019 08:04

@saravanatn как именно это будет работать?

David542 24.04.2019 08:10

@ David542 Дэвид542, я думаю, вам нужно больше разъяснений по вашему вопросу, потому что в соответствии с образцом вывода ваш запрос прост, но ваше описание неясно, пожалуйста, добавьте больше данных в образец.

Zaynul Abadin Tuhin 24.04.2019 08:22

Как насчет того, чтобы у id=2 было несколько типов цен, и оба не были 'TEMP'? Какой из них возьмет .. первый?

FanoFN 24.04.2019 08:33
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
1
4
77
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

попробуйте, как показано ниже, используя объединение и связанный подзапрос

  select id,max(price) as price from prices
  where type='temp' group by id
  union 
  select id,max(price) from prices t1
  where not exists( select 1 from prices t2 where t1.id=t2.id
                   and type='temp')
     group by id

так как вам нужен весь временный тип, поэтому 1-й запрос будет принимать все временные выходные данные, а 2-й запрос будет фильтровать всю временную группу

онлайн демо

выход

id  price
1   30.13
2   14.44

@nikhilsugandh, почему бы и нет

Zaynul Abadin Tuhin 24.04.2019 08:18

лучше возьми это

nikhil sugandh 24.04.2019 08:19

@nikhilsugandh я знаю, что это будет работать в соответствии с образцом вывода, можете ли вы попробовать это на скрипке

Zaynul Abadin Tuhin 24.04.2019 08:20

2 13.33 temp для одной из строк, ваш запрос не будет выполнен, нужно показать 13.33, он покажет 14.44, спасибо

nikhil sugandh 24.04.2019 08:24

@nikhilsugan я понял суть и отредактировал свой ответ, но «продолжайте отрицать все мои вопросы», что это значит, я вас не понимаю

Zaynul Abadin Tuhin 24.04.2019 08:28

Давайте продолжить обсуждение в чате.

Zaynul Abadin Tuhin 24.04.2019 08:30

@nikhilsugandh, почему я удалю, где этот ответ дает мне правильный результат

Zaynul Abadin Tuhin 24.04.2019 08:38
Ответ принят как подходящий

Вы можете использовать следующее решение, используя GROUP BY с MAX:

SELECT id, IFNULL(maxTemp, maxOther) AS maxPrice
FROM (
    SELECT id,
        MAX(CASE WHEN type = 'TEMP' THEN price ELSE NULL END) maxTemp, 
        MAX(CASE WHEN type <> 'TEMP' THEN price ELSE NULL END) maxOther
    FROM table_name
    GROUP BY id
)t;

Это решение должно дать вам правильные результаты для ваших требований (ORDER BY ... DESC LIMIT 1).


Но вы также можете использовать другие агрегатные функции, чтобы получить SUM или список (используя GROUP_CONCAT) ценовых значений.

Решение для получения SUM ценовых значений:

SELECT id, IFNULL(sumTemp, sumOther) AS sumPrice
FROM (
    SELECT id,
        SUM(CASE WHEN type = 'TEMP' THEN price ELSE NULL END) sumTemp, 
        SUM(CASE WHEN type <> 'TEMP' THEN price ELSE NULL END) sumOther
    FROM table_name
    GROUP BY id
)t;

... или получить список ценовых значений с помощью функции GROUP_CONCAT:

SELECT id, IFNULL(gTemp, gOther) AS listPrice
FROM (
    SELECT id,
        GROUP_CONCAT(CASE WHEN type = 'TEMP' THEN price ELSE NULL END) gTemp, 
        GROUP_CONCAT(CASE WHEN type <> 'TEMP' THEN price ELSE NULL END) gOther
    FROM table_name
    GROUP BY id
)t;

демо на dbfiddle.uk

Добавляем скрипку :) dbfiddle.uk/…

Arun Palanisamy 24.04.2019 08:30

@ArunPalanisamy уже работал над скрипкой, но спасибо! - Если возможно, я добавляю скрипку, а также провожу тестирование.

Sebastian Brosch 24.04.2019 08:32

@SebastianBrosch спасибо за этот ответ. Ничего себе, это довольно сложный запрос для относительно «простой» задачи. Спасибо за публикацию, это очень полезно!

David542 24.04.2019 08:33

это будет работать:

select * from(select a.id,a.type,
(select b.price from Table1  b where b.type=a.type and b.type in ('Temp')) mn
from Table1 a group by id,type)ab where mn is not null
union 
select id,type,max(price) from Table1
where type is not null 
and id not in(select id from(select a.id,a.type,
(select b.price from Table1  b where b.type=a.type and b.type in ('Temp')) mn
from Table1 a group by id,type)ab where mn is not null)
group by id,type;

проверить http://sqlfiddle.com/#!9/c166a9/9

Вы можете использовать союз между идентификатором с «TEMP» и запросом для идентификатора без «TEMP».

  select id, price
  from  my_table 
  where type ='TEMP'
  union 
  select id, max(price) 
  from my_table m1
  inner join (
  select id from my_table where id not in (
    selet id
    from my_table 
    where  type 'TEMP'
  ) 
  group by id 
  ) t1 on t1.id= m1.id 

Это, безусловно, самый хакерский подход (два других ответа здесь являются более правильными ответами), но вы также можете использовать оператор CONCAT, чтобы добавить сортировку «в» само поле. Вот основной пример:

SELECT id, RIGHT(
    max(CONCAT(if (type='temp', 1,0), '^', price)),
    length(max(CONCAT(if (type='temp', 1,0), '^', price)))-2
) price FROM prices group by id

1   30.13
2   14.44

Однако, учитывая, что он не зависит от подвыборки, возможно, он будет работать лучше.

Другие вопросы по теме