Opened 7 years ago
Last modified 3 months ago
#28919 assigned New feature
Add support for Common Table Expression (CTE) queries
Description ¶
django-cte-trees (also django-cte-forest) provides specialized uses of CTE queries for managing hierarchical data with recursive queries. To accomplish this, it uses the QuerySet.extra()
API. This is my specific use case for CTE queries at the moment, however it leverages only one small part of what is possible with CTE queries: PostgreSQL, MySQL, SQL Server.
Another implementation supporting more general uses of CTE queries was presented on the developers mailing list, although I'm not sure it has ever made it any further than that. The code can be found on github. It appears to do its magic by mutating base_query.extra_tables
, which seems to be a private/internal part of the ORM.
According to the ticket's flags, the next step(s) to move this issue forward are:
- To provide a patch by sending a pull request. Claim the ticket when you start working so that someone else doesn't duplicate effort. Before sending a pull request, review your work against the patch review checklist. Check the "Has patch" flag on the ticket after sending a pull request and include a link to the pull request in the ticket comment when making that update. The usual format is:
[https://github.com/django/django/pull/#### PR]
.
Change History (41)
comment:1 by , 7 years ago
Triage Stage: | Unreviewed → Accepted |
---|---|
Version: | 2.0 → master |
comment:3 by , 7 years ago
I like Matthew's idea of reusing Subquery as the basis for CTEs since behind the scenes CTEs are really just syntactic sugar for Subqueries. I'd just like to add that being able to pull multiple values/aggregates from the Subquery/CTE would really push this over the top as a huge performance boost for complex analytical queries.
comment:4 by , 7 years ago
Cc: | added |
---|
follow-up: 7 comment:5 by , 7 years ago
I implemented generic CTE support for Django: https://github.com/dimagi/django-cte
Would be happy to contribute this to be included with Django. Feedback is welcome.
comment:6 by , 7 years ago
Cc: | added |
---|
comment:7 by , 7 years ago
Replying to Daniel Miller:
I implemented generic CTE support for Django: https://github.com/dimagi/django-cte
Would be happy to contribute this to be included with Django. Feedback is welcome.
This has worked well for me, with the one exception of not being able to do an outer join since the library just uses extra_tables.
comment:8 by , 7 years ago
I have a PR here, but it's incomplete in some ways: https://github.com/dimagi/django-cte/pull/1
I could use some help from someone more familiar with the Query object and how it handles joins/aliases.
comment:9 by , 7 years ago
It's now been refactored to not use extra_tables
, and there is a secret (undocumented, experimental API) way to do a left outer join.
comment:10 by , 7 years ago
Cc: | added |
---|
comment:11 by , 7 years ago
Cc: | added |
---|
Daniel Miller: Can I humbly suggest you raise this on django-developers? I would guess this needs a discussion of the actual API for adding the table expressions and joining with them.
comment:12 by , 7 years ago
Ole Laursen: that's a good idea. Thank you for the suggestion. I'm a bit busy with other work right now, but I'll add it to my backlog.
comment:13 by , 6 years ago
Cc: | added |
---|
comment:14 by , 6 years ago
Cc: | added |
---|
comment:15 by , 6 years ago
Cc: | added |
---|
comment:16 by , 6 years ago
Cc: | added |
---|
comment:19 by , 5 years ago
Javier, patch is welcome. Leaving comments doesn't change anything and is not helpful.
comment:20 by , 5 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
comment:21 by , 5 years ago
Cc: | added |
---|
comment:22 by , 5 years ago
Cc: | added |
---|
comment:23 by , 5 years ago
Cc: | added |
---|
comment:24 by , 5 years ago
I wonder if this isn't a feature we can combine with the request for adding QuerySet.alias
(#27719).
Adding an alias to a QuerySet
expression would result in a CTE and could then be easily pruned if the queryset drops all references to this alias.
comment:25 by , 5 years ago
Cc: | added |
---|
comment:26 by , 4 years ago
Cc: | added |
---|
comment:27 by , 4 years ago
Cc: | added |
---|
comment:28 by , 4 years ago
Cc: | added |
---|
comment:29 by , 4 years ago
Cc: | added |
---|
comment:30 by , 4 years ago
Cc: | added |
---|
comment:31 by , 3 years ago
Cc: | added |
---|
comment:32 by , 3 years ago
Cc: | added |
---|
comment:33 by , 3 years ago
Cc: | added |
---|
comment:34 by , 3 years ago
Cc: | added |
---|
comment:35 by , 3 years ago
Cc: | added |
---|
comment:36 by , 2 years ago
Cc: | added |
---|
comment:37 by , 2 years ago
Cc: | added |
---|
comment:38 by , 15 months ago
Cc: | added |
---|
comment:39 by , 15 months ago
Cc: | added |
---|
comment:40 by , 13 months ago
Cc: | added |
---|
comment:41 by , 3 months ago
Cc: | added |
---|
I have the same issue. I've been thinking about this and wondering if maybe we could just convert the Subquery object into a CTE (common table expression). They ought to work just the same, and it really shouldn't break backwards compatibility. At the same time, we could add a kwarg to the Subquery object,
recursive
, so that we can create a recursive CTE. I think it would show how powerful the ORM is. It already handles everything else we need with RCTEs, includingunion
queries andunion all
queries.