#sql #sql-server #group-by #range
Вопрос:
У меня есть таблица транзакций с концепцией отправителя и получателя, которые могут отправлять транзакции:
Теперь я хочу получить результирующий набор, который должен включать диапазон количества уникальных отправителей на одного получателя:
- один получатель получает от 1 отправителя
- один получатель получает от 2-5 отправителей
- один получатель получает от 6-10 отправителей
- один получатель получает от 11-20 отправителей
- один получатель получает более 20 отправителей
Я пытался, но не смог получить необходимый набор результатов. Может ли кто-нибудь, пожалуйста, помочь мне в этом.
Комментарии:
1. Вы можете использовать выбрать получателя, количество(отдельный отправитель) …. Пожалуйста, обратите внимание, что изображения не очень полезны, и вы должны предоставить хорошие образцы в виде текста и желаемого результата.
2. @CetinBasoz как я получу получателя, у которого только один отправитель? Если я смогу понять это, у других quries будет похожая картина.
3. Я удалил здесь различные теги версий (одна из которых-версия, которая не поддерживалась более 2 лет). Пометка версии, которую вы используете, полезна, но я сомневаюсь , что вы используете все 3 из них одновременно.
Ответ №1:
Это был бы беспорядок в качестве комментария. Вы на самом деле не предоставили примерные данные и желаемые выходные данные для начала (я не принимаю фотографии в качестве образца). В любом случае, то, что вы описываете, — это простой подсчет():
select receiver, count(distinct sender) senderCount from myTable group by receiver order by count(distinct sender);
сделал бы это. Разложение результата по ведрам, таким как 1, 2-5, … может быть сделано по-разному. т. е.:
with counts(receiver, senderCount) as ( select receiver, count(distinct sender) from myTable group by receiver ) select receiver, case when senderCount = 1 then '1' when senderCount gt; 1 and senderCount lt;= 5 then '2-5' when senderCount gt; 5 and senderCount lt;= 10 then '6-10' when senderCount gt; 10 and senderCount lt;= 20 then '11-20' when senderCount gt; 20 then 'Over 20' end as individualGroup from counts;
Комментарии:
1. Вам также нужно сгруппироваться по тому же
case
выражению2. @SalmanA, о каком падежном выражении вы говорите? Я не вижу такого столбца (в любом случае я не вижу структуры таблицы, кроме вычета из первого рисунка).
3. Он вернет такие данные, как
1, 2-5, 2-5, 11-20
(4 строки), и OP хочет, чтобы они были агрегированы1: 1, 2-5: 2, 11-20: 1
(3 строки)4. @SalmanA, ты уверен в этом? Где это указано?
5. Большое спасибо @CetinBasoz, изучив обсуждение вашего ответа, я понял идею и решил проблему. Извините, что не объяснил это должным образом
Ответ №2:
Создайте (виртуальную) таблицу, в которой хранятся диапазоны, а затем соедините ее с совокупными данными:
SELECT ranges.*, COUNT(*) AS ReceiversInRange --, other aggregates FROM (VALUES (1, 1, 1, 'Low risk'), (2, 2, 5, 'Low risk'), (3, 6, 10, 'Medium risk'), (4, 11, 20, 'Medium-high'), (5, 20, NULL, 'High risk') ) AS ranges(id, lb, ub, label) INNER JOIN ( SELECT COUNT(DISTINCT Sender) AS SenderCount --, other aggregates FROM t GROUP BY Receiver ) AS aggdata ON SenderCount gt;= lb AND (SenderCount lt;= ub OR ub IS NULL) GROUP BY id, lb, ub, label