Вот один из способов сделать это. Ваша группа государственной функции может быть, как это:
CREATE FUNCTION state_group_and_total(state map<text, double>, type text, amount double)
CALLED ON NULL INPUT
RETURNS map<text, double>
LANGUAGE java AS '
Double count = (Double) state.get(type);
if (count == null)
count = amount;
else
count = count + amount;
state.put(type, count);
return state;
';
Это будет построить карту всех сумму выбранных строк по Вашему запросу предложений WHERE. Теперь сложная часть состоит в том, как сохранить только верхнюю часть N. Один из способов сделать это - использовать FINALFUNC, который запускается после того, как все строки были помещены на карту. Итак, вот что нужно сделать, используя цикл, чтобы найти максимальное значение на карте и перенести его на карту результатов. Таким образом, чтобы найти вершину N, она будет перебирать по карте N раз (есть более эффективные алгоритмы, чем это, но это просто быстрый и грязный пример).
Так вот пример, чтобы найти два топ:
CREATE FUNCTION topFinal (state map<text, double>)
CALLED ON NULL INPUT
RETURNS map<text, double>
LANGUAGE java AS '
java.util.Map<String, Double> inMap = new java.util.HashMap<String, Double>(),
outMap = new java.util.HashMap<String, Double>();
inMap.putAll(state);
int topN = 2;
for (int i = 1; i <= topN; i++) {
double maxVal = -1;
String moveKey = null;
for (java.util.Map.Entry<String, Double> entry : inMap.entrySet()) {
if (entry.getValue() > maxVal) {
maxVal = entry.getValue();
moveKey = entry.getKey();
}
}
if (moveKey != null) {
outMap.put(moveKey, maxVal);
inMap.remove(moveKey);
}
}
return outMap;
';
Затем, наконец, вы должны определить агрегатные называть эти две функции вы определили:
CREATE OR REPLACE AGGREGATE group_and_total(text, double)
SFUNC state_group_and_total
STYPE map<text, double>
FINALFUNC topFinal
INITCOND {};
Итак, давайте посмотрим, если это работает ,
CREATE table test (partition int, clustering text, amount double, PRIMARY KEY (partition, clustering));
INSERT INTO test (partition , clustering, amount) VALUES (1, '2015', 99.1);
INSERT INTO test (partition , clustering, amount) VALUES (1, '2016', 18.12);
INSERT INTO test (partition , clustering, amount) VALUES (1, '2017', 44.889);
SELECT * from test;
partition | clustering | amount
-----------+------------+--------
1 | 2015 | 99.1
1 | 2016 | 18.12
1 | 2017 | 44.889
Теперь, барабанная дробь ...
SELECT group_and_total(clustering, amount) from test where partition=1;
agg.group_and_total(clustering, amount)
-------------------------------------------
{'2015': 99.1, '2017': 44.889}
Итак, вы видите, что держали верхние 2 ряда на основе количества.
Обратите внимание, что ключи не будут отсортированы в порядке, так как это карта, и я не думаю, что мы можем контролировать порядок клавиш на карте, поэтому сортировка в FINALFUNC будет пустой тратой ресурсов. Если вам нужна карта, отсортированная, вы можете сделать это в клиенте.
Я думаю, вы могли бы больше работать в функции state_group_and_total, чтобы удалять элементы с карты по мере продвижения. Возможно, лучше держать карту слишком большой.
Отличный ответ! Я собираюсь сделать это. – Aaron
Я пробовал этот, но он показывает ошибку «cqlsh: chris> выберите group_and_total (timestamp, value) со склада; InvalidRequest: code = 2200 [Invalid query] message =" Ошибка типа: значение не может быть p assed as аргумент 1 функции chris.group_and_total типа double " –
Возможно, вы скопировали что-то неправильно. Первый аргумент функции group_and_total в моем примере имеет тип текста, а не double. Опишите описание FUNCTION и описайте AGGREGATE в функциях и убедитесь, что они верны , –