2015-07-24 2 views
0

Для карты choropleth с шестью ячейками я использовал ntile() в PostgreSQL 9.4, чтобы вывести каждое значение в соответствующую группу.PostgreSQL Choropleth Binning

WITH cte AS (
    SELECT random() * 99 + 1 AS value 
    FROM generate_series(1, 1000) 
) 
SELECT value, ntile(6) OVER (ORDER BY value) AS ntile 
FROM cte; 

Результат:

value | ntile 
    ---------+---------- 
    1.08 |  1 
    1.11 |  1 
    ...  |  ... 

Но недавно я наткнулся на некоторые функции биннинга SQL любезно CartoDB (https://github.com/CartoDB/cartodb-postgresql/blob/master/scripts-available/CDB_QuantileBins.sql), и я хотел, чтобы включить эту функцию в моем приложении. Проблема, с которой я столкнулся, заключается в том, что функция CartoDB возвращает массив, в который я должен теперь найти способ поместить каждое значение в соответствующий бит. Есть ли собственный SQL-способ сделать это, возможно, используя функцию window, или это должно быть сделано с помощью специальной функции?

WITH cte AS (
    SELECT ARRAY_AGG(random() * 99 + 1) AS vals 
    FROM generate_series(1,1000) 
) 
SELECT CDB_QuantileBins((SELECT vals FROM cte)::numeric[], 6); 

Результат:

cdb_quantilebins            
----------------------- 
{19.0055054393597,37.2587848943658,53.8059964138083,67.6696971417405,84.0905840680934,99.8241742462851} 
+0

Как вы хотите, чтобы ваш желаемый результат выглядел? –

+0

Я хотел бы, чтобы он выглядел так же, как результат 'ntile()', то есть значение, а затем бит, в который он попал [0, 19.0055], [19.0055, 37.258], .... Например, если значение было 32, я хотел бы, чтобы результат (в JSON, для удобочитаемости) был {"значение": 32, "bin": 2} – hotshotiguana

ответ

0

Только в случае, если кто-то ищет результат в формате значения | bin_number

WITH cte AS (
    SELECT random() * 99 + 1 AS vals 
    FROM generate_series(1,1000) 
), 
bins AS (
SELECT bin, row_number() OVER() AS rank FROM (
SELECT UNNEST(CDB_QuantileBins((SELECT ARRAY_AGG(vals) FROM cte)::numeric[], 6)) bin 
) as f 
) 
SELECT vals, MIN(rank) AS bin_number 
FROM cte 
JOIN bins 
ON bins.bin >= cte.vals 
GROUP BY vals 
1

Если я правильно понимаю, что мы должны UNNEST, а затем найти правильный бункер для каждого Валу.

WITH cte AS (
    SELECT random() * 99 + 1 AS vals 
    FROM generate_series(1,1000) 
), bins AS(
SELECT UNNEST(CDB_QuantileBins((SELECT ARRAY_AGG(vals) FROM cte)::numeric[], 6)) bin 
) 
SELECT vals, min(bin) 
FROM cte 
    JOIN bins 
    ON bins.bin > cte.vals 
GROUP BY vals; 

SQL Fiddle

+0

ОШИБКА: оператор не существует: числовое> двойная точность [] ON bins.bin > cte.vals; – hotshotiguana

+0

@hotshotiguana: Извините, это должно было быть 'UNNEST'. –

+0

Я попробовал его с 'UNNEST', но до сих пор вижу ту же ошибку. Он говорит, что мы не можем сравнивать один номер 'bins.bin' с массивом чисел' cte.vals'. Я думаю, что это определенно правильный подход, но есть только эта последняя небольшая часть. – hotshotiguana