patternsqldjangoMinor
What are the latest Odds?
Viewed 0 times
thelatestoddswhatare
Problem
The main problem the following query is solving, is the following:
Each
I'm pretty sure this is too heavy, so any input would be great.
This is constructed in Django using the following syntax:
This is my schema:
Now what I want to retrieve The
Each
Offer has multiple Odds (Odds has foreignkey to Offer). For each offer I want the latest Odds (ORDER BY time).I'm pretty sure this is too heavy, so any input would be great.
SELECT "odds_odds"."id", "odds_odds"."offer_id", "odds_odds"."time", "odds_odds"."o1", "odds_odds"."o2", "odds_odds"."o3", "odds_odds"."o4", MAX(T3."time") AS "max_time"
FROM "odds_odds"
LEFT OUTER JOIN "odds_offer" ON ( "odds_odds"."offer_id" = "odds_offer"."id" )
LEFT OUTER JOIN "odds_odds" T3 ON ( "odds_offer"."id" = T3."offer_id" )
GROUP BY "odds_odds"."id", "odds_odds"."offer_id", "odds_odds"."time", "odds_odds"."o1", "odds_odds"."o2", "odds_odds"."o3", "odds_odds"."o4"
HAVING "odds_odds"."time" = MAX(T3."time")This is constructed in Django using the following syntax:
Odds.objects.annotate(
max_time=Max('offer__odds__time')
).filter(
time=F('max_time')
)This is my schema:
odds_offer
id (int), .....
odds_odds
id (int), time (datetime), offer_id(int), .....Now what I want to retrieve The
Odds row with the latest time for each Offer. There is a unique constraint on (time, offer_id). One Offer can have multiple odds (historic odds).Solution
Formatting
I think your query could really use some white space to make it easier to read. I realize there is no official standard for SQL, but here is my preferred style:
Table aliases
A table named
Simplifying
You said:
For each offer I want the latest
What I see your code doing is what seems like unnecessary computation to find
I think your query could really use some white space to make it easier to read. I realize there is no official standard for SQL, but here is my preferred style:
SELECT
"odds_odds"."id",
"odds_odds"."offer_id",
"odds_odds"."time",
"odds_odds"."o1",
"odds_odds"."o2",
"odds_odds"."o3",
"odds_odds"."o4",
MAX(T3."time") AS "max_time"
FROM "odds_odds"
LEFT OUTER JOIN "odds_offer"
ON ( "odds_odds"."offer_id" = "odds_offer"."id" )
LEFT OUTER JOIN "odds_odds" T3
ON ( "odds_offer"."id" = T3."offer_id" )
GROUP BY
"odds_odds"."id",
"odds_odds"."offer_id",
"odds_odds"."time",
"odds_odds"."o1",
"odds_odds"."o2",
"odds_odds"."o3",
"odds_odds"."o4"
HAVING "odds_odds"."time" = MAX(T3."time");Table aliases
A table named
"odds_odds" seems odd to me, but you could save some typing by aliasing as odds at least. Also not sure why you are using quotation marks everywhere, but maybe it's a requirement for your system. I have a Postgres database and never needed those, so it just feels like noise. Simplifying
You said:
For each offer I want the latest
Odds (ORDER BY time).What I see your code doing is what seems like unnecessary computation to find
MAX(), where you likely could entirely remove your aggregation and write something along those lines:SELECT
"odds_odds"."id",
"odds_odds"."offer_id",
"odds_odds"."time",
"odds_odds"."o1",
"odds_odds"."o2",
"odds_odds"."o3",
"odds_odds"."o4",
T3."time" AS "max_time"
FROM "odds_odds"
LEFT OUTER JOIN "odds_offer"
ON ( "odds_odds"."offer_id" = "odds_offer"."id" )
LEFT OUTER JOIN "odds_odds" T3
ON ( "odds_offer"."id" = T3."offer_id" )
ORDER BY "odds_odds"."time" DESC
LIMIT 1; -- or however many you needCode Snippets
SELECT
"odds_odds"."id",
"odds_odds"."offer_id",
"odds_odds"."time",
"odds_odds"."o1",
"odds_odds"."o2",
"odds_odds"."o3",
"odds_odds"."o4",
MAX(T3."time") AS "max_time"
FROM "odds_odds"
LEFT OUTER JOIN "odds_offer"
ON ( "odds_odds"."offer_id" = "odds_offer"."id" )
LEFT OUTER JOIN "odds_odds" T3
ON ( "odds_offer"."id" = T3."offer_id" )
GROUP BY
"odds_odds"."id",
"odds_odds"."offer_id",
"odds_odds"."time",
"odds_odds"."o1",
"odds_odds"."o2",
"odds_odds"."o3",
"odds_odds"."o4"
HAVING "odds_odds"."time" = MAX(T3."time");SELECT
"odds_odds"."id",
"odds_odds"."offer_id",
"odds_odds"."time",
"odds_odds"."o1",
"odds_odds"."o2",
"odds_odds"."o3",
"odds_odds"."o4",
T3."time" AS "max_time"
FROM "odds_odds"
LEFT OUTER JOIN "odds_offer"
ON ( "odds_odds"."offer_id" = "odds_offer"."id" )
LEFT OUTER JOIN "odds_odds" T3
ON ( "odds_offer"."id" = T3."offer_id" )
ORDER BY "odds_odds"."time" DESC
LIMIT 1; -- or however many you needContext
StackExchange Code Review Q#65126, answer score: 4
Revisions (0)
No revisions yet.