2013-10-14 4 views
2

Вот сценарий: таблица record выглядит следующим образом:Как HQL может ограничить количество записей в каждой группе?

A | B | C 

1 | 1 | 1 
2 | 1 | 1 
3 | 1 | 1 
4 | 1 | 2 
5 | 1 | 2 
6 | 1 | 3 

результат HQL: select * from record where B = 1 and C < 3 limit 2 будет:

A | B | C 

1 | 1 | 1 
2 | 1 | 1 

Но то, что я хочу это:

A | B | C 

1 | 1 | 1 
2 | 1 | 1 
4 | 1 | 2 
5 | 1 | 2 

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

Мне это действительно нужно Выполняется только в кусте. Может ли кто-нибудь дать мне представление? Большое спасибо!

Чтобы Резюме Вот хороший способ решить эту проблему: http://ragrawal.wordpress.com/2011/11/18/extract-top-n-records-in-each-group-in-hadoophive/

ответ

2

Вы должны быть в состоянии сделать это с помощью UNION запросов.

SELECT A,B,C FROM 
(
    SELECT A, B, C FROM record WHERE B = 1 limit 2 
    UNION AL L 
    SELECT A, B, C FROM record WHERE C < 3 limit 2 
) 

Вы не говорите, как должны выглядеть строки, которые могли бы пройти оба условия; можно добавить DISTINCT к внешнему SELECT, если это необходимо, или вам может потребоваться добавить в пункты WHERE для обработки условий перекрытия.

(да, там не должно быть места в ALL, но фильтрация протоколов отвергают, как она выглядит, как инъекции SQL)

Take 2

На основе замечаний, кажется, что это могло бы быть лучше решить с помощью функции аналитики как цель состоит в том, чтобы получить верхние 2 из каждой группировки в & с, с ограничением из B = 1 C & < 3.

SELECT S.A, S.B, S.C 
FROM 
(SELECT A, B, C, row_number() over (partition by B,C) as r FROM record where B=1 AND C < 3) S 
WHERE S.r < 3 

Это даст результаты по желанию. В этом случае, поскольку B = 1, B действительно не требуется в предложении partition by. Но если будут изменены пределы для B или C, тогда потребуется. Кроме того, если есть некоторые другие отношения между B, C или их значениями, можно изменить с помощью if или case. Например, если C может быть 0, но хотелось бы сгруппировать его с C = 1, вы могли бы сделать

(partition by B, if (C < 2,0,1)) 
+0

Возможно, я не передал это право. После тестирования я не думаю, что это может достичь того, чего я хочу. Вы сказали, что **, как строки, которые могли бы пройти оба условия, должны появиться **, это точно как какая-то ** 'группа by', в каждой группе максимальное количество записей должно быть ограничено **. В этом примере, когда (b = 1 и c = 1) должно быть не более 2 записей, и это то же самое (b = 1 и c = 2) – Judking

+0

** PS ** Если я не описал это ясно, обратитесь к http://stackoverflow.com/questions/10421807/how-do-limit-the-number-of-rows-per-field-value-in-sql?rq=1, это решение в MySQL, но я не знаю, как сделать то же самое в hive.Thanks! – Judking

+0

Я думаю, что ссылка - это другая проблема, она хочет первые 2 строки для каждого отдельного значения в столбце 1; и я только что опубликовал решение для этого. – libjack

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