Improve terrible annotate() query - mysql

Here is the current query I have that orders an order_item by the most recent timestamp.
order_items.annotate(newest_note_time=Max('ordernotes__timestamp')).
order_by('newest_note_time')
It works. However, in viewing it in debug-toolbar it is giving me two brutal queries, that are all but identical. I have tried doing:
order_items = order_items.order_by('-ordernotes__timestamp')
But that results in an incorrect query that gives me duplicate results.
Is there a better way to do this query without jumping into raw SQL here?
Here is one of the queries (the second is basically identical, no idea why it generates a second...)
SELECT ••• FROM `order_orderitem`
INNER JOIN `order_orderitemstatus` ON (`order_orderitem`.`status_id` = `order_orderitemstatus`.`id`)
INNER JOIN `order_order` ON (`order_orderitem`.`order_id` = `order_order`.`id`)
INNER JOIN `title_title` ON (`order_orderitem`.`title_id` = `title_title`.`id`)
INNER JOIN `home_service` ON (`order_orderitem`.`service_id` = `home_service`.`id`)
LEFT OUTER JOIN `order_ordernotes` ON (`order_orderitem`.`id` = `order_ordernotes`.`order_item_id`)
WHERE NOT (`order_orderitemstatus`.`name` IN ('Complete', 'Live', 'Archived'))
GROUP BY
`order_orderitem`.`id`, `order_orderitem`.`order_id`, `order_orderitem`.`title_id`, `order_orderitem`.`service_id`,
`order_orderitem`.`metadata_locale_id`, `order_orderitem`.`purchase_order`, `order_orderitem`.`due_date`, `order_orderitem`.`feature`,
`order_orderitem`.`trailer`, `order_orderitem`.`artwork`, `order_orderitem`.`chaptering`, `order_orderitem`.`cc`,
`order_orderitem`.`metadata`, `order_orderitem`.`subtitles`, `order_orderitem`.`forced_narrative`, `order_orderitem`.`qc_note`,
`order_orderitem`.`audio`, `order_orderitem`.`dub_card`, `order_orderitem`.`live_url`, `order_orderitem`.`metadata_valid`,
`order_orderitem`.`status_id`, `order_orderitem`.`date_created`, `order_order`.`id`, `order_order`.`number`, `order_order`.`provider_id`,
`order_order`.`date_created`, `order_order`.`date_ordered`, `order_order`.`is_archived`, `title_title`.`id`, `title_title`.`film_id`,
`title_title`.`name`, `title_title`.`provider_id`, `title_title`.`original_locale_id`, `title_title`.`country_of_origin_id`,
`title_title`.`synopsis`, `title_title`.`production_company`, `title_title`.`copyright`, `title_title`.`run_time`,
`title_title`.`original_theatrical_release`, `title_title`.`color`, `title_title`.`film_type`, `title_title`.`no_cc_reason`,
`title_title`.`includes_hd`, `title_title`.`provider_identifier`, `title_title`.`episode_production_number`, `title_title`.`container_position`,
`title_title`.`season_id`, `home_service`.`id`, `home_service`.`name`, `home_service`.`notes`, `order_orderitemstatus`.`id`,
`order_orderitemstatus`.`name`, `order_orderitemstatus`.`department_id`, `order_orderitemstatus`.`is_finished`,
`order_orderitemstatus`.`ordering` ORDER BY NULL

.select_related(depth=1)
Add that to the end of your original query and see if any magic happens.
Another possible fix for awful queries that I have is to just cache the page. Add the following to the top of your file:
from django.views.decorators.cache import cache_page
and then just above your def... add:
#cache_page(60 * 5)
which is 60 seconds * 5, for 5 minutes. Change the time to whatever is appropriate for you.

Related

Why are my records blank in my Access query?

I'm trying to run this query:
SELECT tbl_G_ov_wta.PK_G, qry_performPrepElo_wta.PK_G,
qry_performPrepElo_wta.ID1_ocStake
FROM tbl_G_ov_wta
INNER JOIN qry_performPrepElo_wta
ON tbl_G_ov_wta.PK_G = qry_performPrepElo_wta.PK_G
For some reason it won't pull through the values of qry_performPrepElo_wta.ID1_ocStake. Worth mentioning that PK_G is a common primary key. In playing around with this I've found that adding in criteria as follows fixes the issue:
SELECT tbl_G_ov_wta.PK_G, qry_performPrepElo_wta.PK_G,
qry_performPrepElo_wta.ID1_ocStake
FROM tbl_G_ov_wta
INNER JOIN qry_performPrepElo_wta
ON tbl_G_ov_wta.PK_G = qry_performPrepElo_wta.PK_G
WHERE (((tbl_G_ov_wta.PK_G) Between 1 And 1000000));
Any ideas on why this might be?

getting different values, by condition becoming more specific

I have two pieces of code
SELECT * FROM etel.ti18n_country
inner join etel.ti18n
ON id_i18nid = i18nid WHERE id_countryid = 1
and
SELECT * FROM etel.ti18n_country
inner join etel.ti18n
ON id_i18nid = i18nid WHERE id_countryid = 1 and id_i18nid = 4460;
the first results in a bunch of results, but noticably none with id_i18nid = 4460
the second, however gets the result with id_i18nid = 4460.
how can that be? As I understand mysql the first piece of code should've had a result id_i18nid = 4460 for it to be possible for the second piece to have it aswell. Since I made the where clause more specific
Turns out the problem was that I was using Datagrips' ordering to find my id. since I had more than 500 results, datagrip takes random results and orders those. by ending the statement with ORDER BY id_i18nid DESC I found the result.

SQL Query seems not to affect the same number of rows, Adding a count statement

I have made a query that looks like this
Query 1.
SELECT zlec_status.nazwa AS Status,
piorytet.nazwa AS Priorytet,
Concat(koord.imie, ' ', koord.nazwisko) AS `Koordynator`,
Concat(zlec_adresy.miasto, ' - ', zlec_adresy.ulica, ' ',
zlec_adresy.oddzial)
AS `adres`,
zlec_z_dnia,zlec_id,
zlec_nr,
zlec_do,
zlec_ogran,
awizacje,
awizacja_na_dzien,
termin_zamkniecia,
tresc,
uwagi
FROM zlec
INNER JOIN koord
ON zlec.koord = koord.id
INNER JOIN zlec_adresy
ON zlec.zlec_addres = zlec_adresy.id
INNER JOIN piorytet
ON zlec.priorytet = piorytet.id
INNER JOIN zlec_status
ON zlec.status_zlecenia = zlec_status.id
And the following one which is a ordinary one
Query 2.
SELECT * FROM zlec;
The thing is the first one returns ( affects by executing ) 48 rows where the second query returns 103 rows. What could be the possible cause of this?
I will also show you my dumb of the sql in case you would like to make a run on your own http://pastebin.com/cMPAtxCU .
Subquestion - quite no point starting of with a new question for that because its also connected with the row count affect.
Besides I was wondering how can I get into the first query a count(*) to get the affected rows - it has to be done in sql I cannot use php code for that, probably it would be good to use a limit 1 for the count.
With INNER JOIN, if one of your other tables, koord, zlec_adresy, piorytet and zlec_status is missing a record corresponding to a record in zlec, that record in zlec will not be in the result set. If you want every record in zlec to appear, you have to use LEFT JOIN. Check out:
http://blog.codinghorror.com/a-visual-explanation-of-sql-joins/
For a pretty good explanation.
With your additional inner joins rows might be eliminated. Have you tried adding the inner joins to your "Select * FROM zlec;"?

SQL - OutterApply and Left Join

I'm working with a large stored procedure, I'm having trouble with a small portion of it.
When I execute a query on the table im joining, there can be 0, 1 or 2 results. If there are 0 results, I don't really care, my code returns null values, no big deal. If there is 1 result, my code returns the correct values, however, if there are 2 results, I am having trouble selecting the second result.
My code below works until the second OutterApply(the AHM2 stuff). Does anyone see what I am doing wrong?
The animal ID is identical for both OuterApplys. I just need to return the second result, if there is one, and if it is not the same as the first one.
SELECT TOP 1
AHM.AnimalHerdManagementId,
AHM.HerdManagementId,
AHM2.AnimalHerdManagementId,
AHM2.HerdManagementId,
HM.Code AS HerdManagementCode,
HM2.Code AS HerdManagementCode2
OUTER APPLY
(
SELECT TOP 1 AHM.AnimalHerdManagementId, AHM.HerdManagementId
FROM dbo.AnimalHerdManagement AHM
WHERE AHM.AnimalId = A.AnimalId AND ISNULL(AHM.EffectiveFrom, #EffectiveFrom) <= #EffectiveFrom
ORDER BY AHM.EffectiveFrom DESC
) AHM
LEFT JOIN dbo.HerdManagement HM ON AHM.HerdManagementId = HM.HerdManagementId
OUTER APPLY
(
SELECT TOP 1 AHM2.AnimalHerdManagementId, AHM2.HerdManagementId
FROM dbo.AnimalHerdManagement AHM2
WHERE AHM2.AnimalId = A.AnimalId AND AHM2.AnimalHerdManagementId != AHM.AnimalHerdManagementId AND ISNULL(AHM2.EffectiveFrom, #EffectiveFrom) <= #EffectiveFrom
ORDER BY AHM2.EffectiveFrom DESC
) AHM2
LEFT JOIN dbo.HerdManagement HM2 ON AHM2.HerdManagementId = HM2.HerdManagementId
I think I can help you with the OUTER APPLY but the method of getting the two different values is going to need some help as my solution is a total hack.
First, you don't need to join on the outer apply. The join is implied. So you can completely eliminate the join syntax from your query.
Second, AnimalHerdManagement looks/seems like a special table called a Junction Table. All the data contained in it is contained elsewhere (That it contains completely redundant data is why it's called a special table). But that is minor.
Finally, here is some example code I threw together that accomplishes what you are after. The method I am using to retrieve different results on the two outer apply's is a hack, but if you are sure that will always be true, it might work. I am not able to get a multi-level outer apply to work.
select * from AH_Animal A
outer apply
(
select max (HerdManagementID) as HerdMgmtID1 from AH_AnimalHerdManagement HM1 where HM1.AnimalID = A.AnimalID
) as z
outer apply
(
select min (HerdManagementID) as HerdMgmtID2 from AH_AnimalHerdManagement HM2 where HM2.AnimalID = A.AnimalID
) as zz
I hope that helped. There has to be another solution to this, as this would not work at all if you ever expected 3 results.
Query Results:

MYSQL get other table data in a join

I am currently running this SQL
SELECT jm_recipe.name, jm_recipe.slug
FROM jm_recipe
LEFT JOIN jm_category_recipe ON jm_category_recipe.recipe_id = jm_recipe.id
WHERE jm_category_recipe.category_id = $cat"
This returns the desired results except that I also need to return the name of the category that the recipe I am looking for is in, to do this I tried to add the field in to my SELECT statement and also add the table into the FROM clause,
SELECT jm_recipe.name, jm_recipe.slug, jm_category_name
FROM jm_recipe, jm_category
LEFT JOIN jm_category_recipe ON jm_category_recipe.recipe_id = jm_recipe.id
WHERE jm_category_recipe.category_id = $cat"
However this just returns no results, what am i doing wrong?
You need to join both tables:
SELECT jm_recipe.name, jm_recipe.slug, jm.category_name
FROM jm_recipe
INNER JOIN jm_category_recipe ON jm_category_recipe.recipe_id = jm_recipe.id
INNER JOIN jm_category ON jm_recipe.recipe_id = jm_category.recipe_id
WHERE jm_category_recipe.category_id = $cat
I've changed the joins to inner joins as well. You might want to make them both LEFT joins if you have NULLs and want them in the result.
Also, you're vulnerable to SQL Injection by simply copying over $cat.
Here's some PHP specific info for you (I'm assuming you're using PHP.)