2015-08-05 4 views
4

Мне нужна помощь. У меня есть запрос, который получает 5 лучших записей по дате (не дата + время) и сумма суммы.Как получить 5 лучших записей в cassandra 2.2

я писал, но он возвращает все записи не только топ 5 записей

CREATE OR REPLACE FUNCTION state_groupbyandsum(state map<text, double>, datetime text, amount text) 
CALLED ON NULL INPUT 
RETURNS map<text, double> 
LANGUAGE java 
AS 'String date = datetime.substring(0,10); Double count = (Double) state.get(date); if (count == null) count = Double.parseDouble(amount); else count = count + Double.parseDouble(amount); state.put(date, count); return state;' ; 


CREATE OR REPLACE AGGREGATE groupbyandsum(text, text) 
SFUNC state_groupbyandsum 
STYPE map<text, double> 
INITCOND {}; 

select groupbyandsum(datetime, amout) from warehouse; 

Не могли бы вы помочь получить только 5 записей.

ответ

3

Вот один из способов сделать это. Ваша группа государственной функции может быть, как это:

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, чтобы удалять элементы с карты по мере продвижения. Возможно, лучше держать карту слишком большой.

+0

Отличный ответ! Я собираюсь сделать это. – Aaron

+0

Я пробовал этот, но он показывает ошибку «cqlsh: chris> выберите group_and_total (timestamp, value) со склада; InvalidRequest: code = 2200 [Invalid query] message =" Ошибка типа: значение не может быть p assed as аргумент 1 функции chris.group_and_total типа double " –

+0

Возможно, вы скопировали что-то неправильно. Первый аргумент функции group_and_total в моем примере имеет тип текста, а не double. Опишите описание FUNCTION и описайте AGGREGATE в функциях и убедитесь, что они верны , –

Смежные вопросы