Can peewee nest SELECT queries such that the outer

2019-04-12 14:57发布

I'm using peewee2.1 with python3.3 and an sqlite3.7 database.

I want to perform certain SELECT queries in which:

  1. I first select some aggregate (count, sum), grouping by some id column; then
  2. I then select from the results of (1), aggregating over its aggregate. Specifically, I want to count the number of rows in (1) that have each aggregated value.

My database has an 'Event' table with 1 record per event, and a 'Ticket' table with 1..N tickets per event. Each ticket record contains the event's id as a foreign key. Each ticket also contains a 'seats' column that specifies the number of seats purchased. (A "ticket" is really best thought of as a purchase transaction for 1 or more seats at the event.)

Below are two examples of working SQLite queries of this sort that give me the desired results:

SELECT ev_tix, count(1) AS ev_tix_n FROM 
(SELECT count(1) AS ev_tix FROM ticket GROUP BY event_id)
GROUP BY ev_tix

SELECT seat_tot, count(1) AS seat_tot_n FROM
(SELECT sum(seats) AS seat_tot FROM ticket GROUP BY event_id)
GROUP BY seat_tot

But using Peewee, I don't know how to select on the inner query's aggregate (count or sum) when specifying the outer query. I can of course specify an alias for that aggregate, but it seems I can't use that alias in the outer query.

I know that Peewee has a mechanism for executing "raw" SQL queries, and I've used that workaround successfully. But I'd like to understand if / how these queries can be done using Peewee directly.

1条回答
劫难
2楼-- · 2019-04-12 15:22

I posted the same question on the peewee-orm Google group. Charles Leifer responded promptly with both an answer and new commits to the peewee master. So although I'm answering my own question, obviously all credit goes to him.

You can see that thread here: https://groups.google.com/forum/#!topic/peewee-orm/FSHhd9lZvUE

But here's the essential part, which I've copied from Charles' response to my post:

I've added a couple commits to master which should make your queries possible (https://github.com/coleifer/peewee/commit/22ce07c43cbf3c7cf871326fc22177cc1e5f8345).

Here is the syntax,roughly, for your first example:

SELECT ev_tix, count(1) AS ev_tix_n FROM 
(SELECT count(1) AS ev_tix FROM ticket GROUP BY event_id)
GROUP BY ev_tix
ev_tix = SQL('ev_tix')  # the name of the alias.
(Ticket
 .select(ev_tix, fn.count(ev_tix).alias('ev_tix_n'))
 .from_(
     Ticket.select(fn.count(Ticket.id).alias('ev_tix')).group_by(Ticket.event))
.group_by(ev_tix))

This yields the following SQL:

SELECT ev_tix, count(ev_tix) AS ev_tix_n FROM (SELECT Count(t2."id") 
AS ev_tix FROM "ticket" AS t2 GROUP BY t2."event_id")
GROUP BY ev_tix
查看更多
登录 后发表回答