2015-09-30 2 views
1

J'essaye de faire une demande de cqlsh sur Cassandra. L'idée est d'analyser la longueur moyenne de différents registres «géniques» qui ont été annotés dans un génome. Après entrer les données, j'ai cette table athaliana.tab:Quelle est la meilleure façon d'effectuer une soustraction sur Cassandra par une requête cqlsh?

id         | chr | comments   | end  | orf | sense | start | type 
--------------------------------------+-----+-------------------+----------+-----+-------+----------+------ 
d2ab2520-6734-11e5-955c-234085c1edec | 1 | gene_id AT1G16340 | 5590338 | 0 |  - | 5590241 | CDS 
d4169c00-6734-11e5-955c-234085c1edec | 1 | gene_id AT1G16610 | 5676495 | . |  - | 5676429 | exon 
a8c792c0-6734-11e5-955c-234085c1edec | 1 | gene_id AT1G07485 | 2301889 | 0 |  + | 2301665 | CDS 
3bd5c0a0-6735-11e5-955c-234085c1edec | 1 | gene_id AT1G51980 | 19326916 | . |  - | 19326733 | exon 
263b5b60-6735-11e5-955c-234085c1edec | 1 | gene_id AT1G44990 | 17007808 | . |  - | 17007542 | gene 
67989a50-6735-11e5-955c-234085c1edec | 1 | gene_id AT1G63110 | 23405144 | . |  + | 23404821 | UTR 
26f7f4a0-6735-11e5-955c-234085c1edec | 1 | gene_id AT1G45180 | 17101207 | 0 |  + | 17101109 | CDS 
3743dc70-6735-11e5-955c-234085c1edec | 1 | gene_id AT1G50840 | 18841644 | 0 |  + | 18840965 | CDS 
e5099940-6734-11e5-955c-234085c1edec | 1 | gene_id AT1G20620 | 7145780 | . |  + | 7145691 | exon 
2ba30620-6735-11e5-955c-234085c1edec | 1 | gene_id AT1G48180 | 17793717 | . |  - | 17792449 | gene 

L'idée est d'obtenir la soustraction entre les colonnes de fin données de début et de calculer la moyenne. J'ai essayé de cette façon:

SELECT avg(end-start) FROM athaliana.tab WHERE chr = '1' AND type = 'gene'; 

mais il se traduit par:

SyntaxException: <ErrorMessage code=2000 [Syntax error in CQL query] message="line 1:14 no viable alternative at input '-' (SELECT avg([end]-...)"> 

Quelques idées? Toute aide sera vraiment appréciée.

Répondre

4

Cassandra est conçu pour un maximum de lire et d'écrire l'efficacité et n'a pas de support intégré pour les fonctions applicables à plusieurs colonnes telles que plus ou minus ni pour agrégats, à savoir les fonctions applicables à plusieurs lignes, telles que avg ou count . Jusqu'à récemment, la solution consistait à stocker les résultats de vos fonctions dans une colonne séparée et à effectuer des agrégations dans votre propre code d'application.

Cependant, Cassandra 2.2 et 3.0 offrent maintenant fonctions définies par l'utilisateur (FDU) et agrégats définis par l'utilisateur() EDU. Vous pouvez maintenant définir vos propres fonctions, puis demandez à Cassandra de les appeler pour vous. Voir les chapitres de spécification CQL sur UDFs et UDAs ou this blog post.

D'abord, créer les fonctions et les agrégats suivants:

USE athaliana; 

CREATE FUNCTION minus (x int, y int) RETURNS NULL ON NULL INPUT RETURNS int LANGUAGE java AS 'return x-y;'; 

CREATE FUNCTION avgState (state tuple<int,bigint>, val int) CALLED ON NULL INPUT RETURNS tuple<int,bigint> LANGUAGE java AS ' 
    if (val != null) { 
     state.setInt(0, state.getInt(0)+1); 
     state.setLong(1, state.getLong(1)+val.intValue()); 
    } 
    return state; 
'; 

CREATE FUNCTION avgFinal (state tuple<int,bigint>) CALLED ON NULL INPUT RETURNS double LANGUAGE java AS ' 
    double r = 0; 
    if (state.getInt(0) == 0) return null; 
    r = state.getLong(1); 
    r /= state.getInt(0); 
    return Double.valueOf(r); 
    '; 

CREATE AGGREGATE avg(int) SFUNC avgState STYPE tuple<int,bigint> FINALFUNC avgFinal INITCOND (0, 0); 

Ensuite, votre requête pourrait être réécrite ainsi:

SELECT avg(minus(end,start)) FROM athaliana.tab WHERE chr = '1' AND type = 'gene'; 

Notez que vous ne devez utiliser des agrégats sur une seule clé de partition; Si ce n'est pas le cas, un avertissement sera émis.

+0

Wow, réponse géniale! – Aaron

+0

Bonne approche, merci beaucoup! –