Пометить верхние 90% строк в каждом разделе таблицы - PullRequest
2 голосов
/ 18 июня 2019

У меня есть таблица, как показано ниже. Я хочу получить столбец Flag таким образом, чтобы примерно в верхних 90% строк каждого раздела было TypeA, а в оставшихся 10% строк будет иметь TypeB в качестве флага.

+------+----+
| City | id |
+------+----+
| A    | 1A |
| A    | 2A |
| A    | 3A |
| A    | 4A |
| A    | 5A |
| B    | 1B |
| B    | 2B |
| B    | 3B |
| B    | 4B |
| B    | 5B |
| B    | 6B |
| D    | 1D |
| D    | 2D |
| D    | 3D |
| D    | 4D |
| D    | 5D |
| D    | 6D |
| D    | 7D |
| D    | 8D |
+------+----+

Желаемый результат

+------+----+-------+
| City | id | Flag  |
+------+----+-------+
| A    | 1A | TypeA |
| A    | 2A | TypeA |
| A    | 3A | TypeA |
| A    | 4A | TypeA | // Approximately Top 90% of rows for City A: Flag Type A
| A    | 5A | TypeB | // Approximately below 10% of rows for City A: Flag Type B
| B    | 1B | TypeA |
| B    | 2B | TypeA |
| B    | 3B | TypeA |
| B    | 4B | TypeA |// Approximately Top 90% of rows for City B: Flag Type A
| B    | 5B | TypeB |// Approximately below 10% of rows for City B: Flag Type B
| B    | 6B | TypeB |
| D    | 1D | TypeA |
| D    | 2D | TypeA |
| D    | 3D | TypeA |
| D    | 4D | TypeA |
| D    | 5D | TypeA |
| D    | 6D | TypeA |
| D    | 7D | TypeA |
| D    | 8D | TypeB |
+------+----+-------+

Любая помощь будет по достоинству оценена.

SQL Fiddle

Ответы [ 3 ]

3 голосов
/ 18 июня 2019

Вот один вариант, использующий COUNT в качестве аналитической функции:

SELECT
    City,
    id,
    CASE WHEN COUNT(*) OVER (PARTITION BY City ORDER BY id) /
        COUNT(*) OVER (PARTITION BY City) <= 0.9
         THEN 'TypeA'
         ELSE 'TypeB' END AS Flag
FROM yourTable
ORDER BY
    City,
    Id;

enter image description here

Демо

При первом вызове COUNT вычисляется количество элементов в каждом городском разделе до текущей строки в соответствии с порядком Id. Затем мы нормализуем это по общему количеству записей для каждого города и сравним это с 0.9, чтобы решить, какой флаг назначить.

3 голосов
/ 18 июня 2019

Один из методов - явный подсчет:

select t.*,
       (case when row_number() over (partition by city order by id) <=
                  0.9 * count(*) over (partition by city)
             then 'TypeA'
             else 'TypeB'
        end) as flag
from t
2 голосов
/ 18 июня 2019

SQL Server имеет оконную функцию процентов_кран () для прямого вычисления нужного числа без необходимости делать это самостоятельно:

SELECT City, id
     , CASE
        WHEN percent_rank() OVER (PARTITION BY City ORDER BY id) <= 0.9 THEN 'TypeA'
        ELSE 'TypeB'
       END AS Flag
FROM table1
ORDER BY City, id;

Скрипка .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...