Knex: Comment effectuer des sommes complexes

Créé le 4 août 2016  ·  3Commentaires  ·  Source: knex/knex

_(Remarque : j'utilise Postgres ; cela peut ne pas s'appliquer à d'autres dialectes)_

J'ai une requête qui renvoie un score moyen, et le nombre de personnes qui ont réussi, un quiz. Voici une version simplifiée de ce que j'essaye de faire :

knex( 'quiz_submissions AS qs' )
        .select( 'q.name AS quiz_name' )
        .avg( 'qs.score' )
        .sum( '(case when qs.score >= 60 then 1 else 0 end) AS passedCount' )
        .innerJoin( 'quizzes AS q', 'q.id', 'qs.quiz_id' )
        .groupBy( 'q.name' );

(Notez le sum )

Malheureusement, cela ne rend pas la fonction SUM comme je m'y attendais :

sum("(case when qs"."score >= 60 then 1 else 0 end)") as "passedCount"
  1. Existe-t-il actuellement un moyen de faire des sommes "complexes" ?
  2. Sinon, est-ce que quelqu'un s'oppose à ce que j'ajoute une fonction sumRaw ?

Commentaire le plus utile

Trouvé une solution de contournement dans #238 ; Faites le knex.raw dans le select plutôt que le sum . Cela semble évident maintenant que je l'écris...

knex( 'quiz_submissions AS qs' )
    .select( 'q.name AS quiz_name', knex.raw( 'SUM(case when qs.score >= 60 then 1 else 0 end) AS passedCount' ) )
    .avg( 'qs.score' )
    .innerJoin( 'quizzes AS q', 'q.id', 'qs.quiz_id' )
    .groupBy( 'q.name' );

Tous les 3 commentaires

Est-ce que ça marche si vous enveloppez votre argument à sum avec knex.raw ?

Ça n'en a pas l'air... Si je change la somme en ceci :

.sum( knex.raw( '(case when qs.score >= 60 then 1 else 0 end) AS passedCount' ) )

J'obtiens l'erreur "val.toLowerCase n'est pas une fonction"

(J'ai essayé avec des parenthèses, sans, en ajoutant l'alias as , en l'enlevant, l'erreur était la même à chaque fois)

Trace de la pile:

TypeError: val.toLowerCase is not a function
    at QueryCompiler_PG.aggregate (../../src/query/compiler.js:166:25)
    at QueryCompiler_PG.columns (../../src/query/compiler.js:152:25)
    at ../../src/query/compiler.js:82:22
    at Array.map (native)
    at QueryCompiler_PG.select (../../src/query/compiler.js:81:35)
    at QueryCompiler_PG.toSQL (../../src/query/compiler.js:45:5)
    at QueryBuilder.toSQL (../../src/query/builder.js:41:49)
    at ../src/runner.js:34:7
    at tryCatcher (util.js:16:23)
    at using.js:185:26
    at tryCatcher (util.js:16:23)
    at Promise._settlePromiseFromHandler (promise.js:504:31)
    at Promise._settlePromise (promise.js:561:18)
    at Promise._settlePromise0 (promise.js:606:10)
    at Promise._settlePromises (promise.js:685:18)
    at Promise._fulfill (promise.js:630:18)
From previous event:
    at Promise.longStackTracesCaptureStackTrace [as _captureStackTrace] (debuggability.js:369:19)
    at Promise._then (promise.js:230:17)
    at Promise.then (promise.js:123:17)
    at Function.Promise.using (using.js:169:14)
    at Runner.run (../src/runner.js:27:20)
    at QueryBuilder.Target.then (../src/interface.js:22:50)
    at process._tickCallback (node.js:369:9)

La version de knex est 0.11.7, bien que j'aie mis à jour vers 0.11.9 et ai reçu le même message.

Trouvé une solution de contournement dans #238 ; Faites le knex.raw dans le select plutôt que le sum . Cela semble évident maintenant que je l'écris...

knex( 'quiz_submissions AS qs' )
    .select( 'q.name AS quiz_name', knex.raw( 'SUM(case when qs.score >= 60 then 1 else 0 end) AS passedCount' ) )
    .avg( 'qs.score' )
    .innerJoin( 'quizzes AS q', 'q.id', 'qs.quiz_id' )
    .groupBy( 'q.name' );
Cette page vous a été utile?
0 / 5 - 0 notes