#sql #group-by #count
#sql #группировать по #количество
Вопрос:
У меня есть таблица, отображающая три столбца: A, B, C. Столбец A имеет повторяющиеся значения. Как мне отсортировать результаты на основе столбца C?
Например:
A B C
Amanda healthy
Amanda healthy
Brian healthy
Brian sick
Brian healthy
Colleen [null]
Colleen sick
Tyler healthy
Tyler [null]
Tyler fever
Daniel [null]
Daniel [null]
Daniel [null]
Итак, это всего лишь пример. Я оставил столбец B пустым, потому что здесь это не имеет большого значения. То, что я пытаюсь сделать, это агрегировать дубликаты в A на основе результатов в C. Если все результаты равны нулю, то это должно показать мне значение 0. Если все результаты исправны или представляют собой смесь исправных и нулевых значений, то мне нужно значение 1. Если в результатах есть какое-либо упоминание о болезни, я хочу, чтобы это было значением 2.
Так, например, в приведенном выше примере я хочу, чтобы Аманда присвоила мне значение 1, Брайан 2, Коллин 2, Тайлер 2, Дэниел 0. Есть мысли о том, как я могу это сделать? Спасибо!
Комментарии:
1. Пожалуйста, поделитесь тем, что вы пробовали, чтобы вы могли получить лучшее решение
2. Пожалуйста, отметьте свою СУБД (какую БД вы используете: MySQL, MSSQL и т.д.).
Ответ №1:
Из ваших данных и результатов это выглядит как хотите count(distinct)
:
select a, count(distinct c) cnt
from mytbale
group by a
Из описания вашего вопроса это немного отличается. Вы можете использовать case
выражение:
select
a,
case
when max(case when c = 'sick' then 1 else 0 end) = 1 then 2
when max(case when c = 'healthy' then 1 else 0 end) = 1 then 1
when count(c) = 0 then 0
end as res
from mytable
group by a
Комментарии:
1. Я думаю, что дело необходимо переупорядочить, чтобы больной случай был перед здоровым случаем, потому что требование состоит в том, что как только появляется хотя бы один больной, результат должен быть 2, и выигрывает первый соответствующий случай.
Ответ №2:
Первый шаг: зарегистрируйте инциденты (да / нет = 1/0) возможных результатов в C для каждого A:
SELECT a,BIT_XOR(CASE WHEN c IS NULL THEN 1 WHEN c="healthy" THEN 2 ELSE 4 END) FROM table GROUP BY a;
(здесь я предположил, что «болезнь» и «лихорадка» должны обрабатываться аналогично, поскольку вы не указали, что, например, все «лихорадки» должны давать)
В этом запросе выходные данные являются:
- 1, если все равно NULL (для c).
- 2, если все «исправно».
- 3 если все «исправные» (по крайней мере 1) или НУЛЕВЫЕ (по крайней мере один)
- в противном случае (1xxb), если есть хотя бы один случай «болезни» / «лихорадки».
Чтобы адаптировать эти выходные данные к вашим желаемым значениям (0/1/1/2 для соответствующих случаев), запрос может быть адаптирован, например
SELECT a,If(bitmap=1,0,IF(bitmapamp;4,2,1)) FROM
(SELECT a,BIT_XOR(CASE WHEN c IS NULL THEN 1 WHEN c="healthy" THEN 2 ELSE 4 END) bitmap FROM table GROUP BY a) tmp;
PS: если у вас аллергические реакции на этот вложенный запрос (например, потому что сервер SQL может не оптимизировать его сам), просто перепишите его в один запрос, повторив внутреннее выражение, или просто переведите значения исходного запроса на принимающей стороне.
Ответ №3:
Этот сценарий предназначен для oracle, но «select» — это SQL-92. Надеюсь, это будет полезно для вас.
create table anamnesis (
a varchar(20),
c varchar(20)
);
INSERT ALL
INTO anamnesis (a, c) VALUES ('Amanda','healthy')
INTO anamnesis (a, c) VALUES ('Amanda','healthy')
INTO anamnesis (a, c) VALUES ('Brian','healthy')
INTO anamnesis (a, c) VALUES ('Brian','sick')
INTO anamnesis (a, c) VALUES ('Brian','healthy')
INTO anamnesis (a, c) VALUES ('Colleen',null)
INTO anamnesis (a, c) VALUES ('Colleen','sick')
INTO anamnesis (a, c) VALUES ('Tyler','healthy')
INTO anamnesis (a, c) VALUES ('Tyler',null)
INTO anamnesis (a, c) VALUES ('Tyler','fever')
INTO anamnesis (a, c) VALUES ('Daniel',null)
INTO anamnesis (a, c) VALUES ('Daniel',null)
INTO anamnesis (a, c) VALUES ('Daniel',null)
SELECT * FROM dual;
select t.a, (case when sick>0 then 2 else
case when healthy>0 then 1 else
0
end
end
) res
from
(select
t.a,
sum(case when t.c is null then 1 else 0 end) nullable,
sum(case when t.c='healthy' then 1 else 0 end) healthy,
sum(case when coalesce(t.c,'-') not in ('-','healthy') then 1 else 0 end) sick
from
anamnesis t
group by t.a) t;