Альтернатива объединению и где утверждение для возраста и группы сегментов по столбцу SQL Импала - PullRequest
1 голос
/ 20 марта 2020

Учитывая таблицу как:

+----+-----------+------------------+
| id | code      | age              |
+----+-----------+------------------+
| 1  | 315.32000 | 2.18430371791803 |
| 1  | 315.32000 | 3.18430371791803 |
| 1  | 800.00000 | 2.18430371791803 |
| 2  | 315.32000 | 5.64822705794013 |
| 3  | 800.00000 | 5.68655778752176 |
| 3  | 120.12000 | 5.70572315231258 |
| 4  | 315.32000 | 5.72488851710339 |
| 4  | 315.32000 | 5.74405388189421 |
| 5  | 120.12000 | 5.7604813374292  |
| 6  | 315.32000 | 5.77993740687426 |
| .. | ...       | ...              |
+----+-----------+------------------+

Я использую:

SELECT code, COUNT(*) AS code_frequency,'0-10' AS age_range
FROM table 
WHERE age >= 0 AND age < 10
GROUP BY code 
ORDER BY code_frequency DESC LIMIT 1
UNION
SELECT code, COUNT(*) AS code_frequency,'10-20' AS age_range
FROM table
WHERE age >= 10 AND age < 20
GROUP BY code 
ORDER BY code_frequency DESC LIMIT 1
UNION
...
ORDER BY age_range

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

output:

+-----------+-----------+-----------+
| code      | frequency | age_range |
+-----------+-----------+-----------+
| 315.32000 | 99832     | 0-10      |
| 800.00000 | 45223     | 10-20     |
| ...       | ...       | ...       |
+-----------+-----------+-----------+

Существует ли более эффективный способ достижения того же самого вывод, без повторения тех же блоков кода и без использования объединения?

Cheers

1 Ответ

2 голосов
/ 20 марта 2020

Вы можете использовать агрегацию с выражением case для определения группы:

select
    code,
    count(*) frequency,
    case 
        when age >= 0  and age < 10 then '0-10'
        when age >= 10 and age < 20 then '10-20'
    end age_range
from mytable
group by code, age_range
order by age_range

Если вы хотите использовать наиболее частый код для каждой возрастной группы, тогда вы можете использовать row_number() поверх запроса :

select code, frequence, age_range
from (
    select 
        t.*, 
        row_number() over(partition by age_range order by frequency desc) rn
    from (
        select
            code,
            count(*) frequency,
            case 
                when age >= 0  and age < 10 then '0-10'
                when age >= 10 and age < 20 then '10-20'
            end age_range
        from mytable
        group by code, age_range
    ) t
) t
where rn = 1

Или еще лучше:

select code, frequence, age_range
from (
    select
        code,
        count(*) frequency,
        case 
            when age >= 0  and age < 10 then '0-10'
            when age >= 10 and age < 20 then '10-20'
        end age_range,
        row_number() over(partition by min(age) order by count(*) desc) rn
    from mytable
    group by code, age_range
) t
where rn = 1
...