How to implement the having clause in sqlite django ORM - python

I've written django sqlite orm syntax to retrieve particular set of records:
from django.db.models.aggregates import Count
JobStatus.objects.filter(
status='PRF'
).values_list(
'job', flat=True
).order_by(
'job'
).aggregate(
Count(status)__gt=3
).distinct()
But it gives me an error and the sql equivalent for this syntax works fine for me.
This is my sql equivalent.
SELECT *
FROM tracker_jobstatus
WHERE status = 'PRF'
GROUP BY job_id
HAVING COUNT(status) > 3;
and I'm getting the result as follows
+----+--------+--------+---------+---------------------+---------+
| id | job_id | status | comment | date_and_time | user_id |
+----+--------+--------+---------+---------------------+---------+
| 13 | 3 | PRF | | 2012-11-12 13:16:00 | 1 |
| 31 | 4 | PRF | | 2012-11-12 13:48:00 | 1 |
+----+--------+--------+---------+---------------------+---------+
I'm unable to find the django sqlite equivalent for this.
I will be very grateful if anyone can help.

Finally I've managed to figure it out. The ORM syntax is something like this.
from django.db.models.aggregates import Count
JobStatus.objects.filter(
status='PRF'
).values_list(
'job', flat=True
).order_by(
'job'
).annotate(
count_status=Count('status')
).filter(
count_status__gt=1
).distinct()

More general rule for this: you need to create new column (by annotate) and then filter through that new column. This queryset will be transformed to HAVING keyword.

Related

Trouble with SQL join, where, having clause

I'm having trouble understanding how to make a query that will show me 'the three most popular articles' in terms of views ('Status: 200 OK').
There are 2 tables I'm currently dealing with.
A Log table
An Articles table
The columns in these tables:
Table "public.log"
Column | Type | Modifiers
--------+--------------------------+--------------------------------------------------
path | text |
ip | inet |
method | text |
status | text |
time | timestamp with time zone | default now()
id | integer | not null default nextval('log_id_seq'::regclass)
Indexes:
and
Table "public.articles"
Column | Type | Modifiers
--------+--------------------------+-------------------------------------------------------
author | integer | not null
title | text | not null
slug | text | not null
lead | text |
body | text |
time | timestamp with time zone | default now()
id | integer | not null default nextval('articles_id_seq'::regclass)
Indexes:
.
So far, I've written this query based on my level and current understanding of SQL...
SELECT articles.title, log.status
FROM articles join log
WHERE articles.title = log.path
HAVING status = “200 OK”
GROUP BY title, status
Obviously, this is incorrect. I want to be able to pull the three most popular articles from the database and I know that 'matching' the 200 OK's with the "article title" will show or count in for me one "view" or hit. My thought process is like, I need to determine how many times that article.title=log.path (1 unique) shows up in the log database (with a status of 200 OK) by creating a query. My assignment is actually to write a program that will print the results with "[my code getting] the database to do the heavy lifting by using joins, aggregations, and the where clause.. doing minimal "post-processing" in the Python code itself."
Any explanation, idea, a tip is appreciated all of StackOverflow...
Perhaps the following is what you have in mind:
SELECT
a.title,
COUNT(*) AS cnt
FROM articles a
INNER JOIN log l
ON a.title = l.path
WHERE
l.lstatus = '200 OK'
GROUP BY
a.title
ORDER BY
COUNT(*) DESC
LIMIT 3;
This would return the three article titles having the highest status 200 hit counts. This answer assumes that you are using MySQL.

how to get latest timestamp from the two columns in django

How can I get latest time from two columns eg I have two column name start_time_a and start_time_b both stores value like 2014-05-13 12:34:34 but i need to get latest time from the two columns using Python Django. I am new to django query please help me to get rid of this issue.
Example table:
+-----+-----------------------+-----------------------+
| id | start_time_a | start_time_b |
+-----+-----------------------+-----------------------+
| 1 | 2014-05-13 12:34:34 | 2014-05-13 12:41:34 |
| 2 | 2014-05-13 12:40:34 | 2014-05-13 12:40:40 |
| 3 | 2014-05-13 12:20:34 | 2014-05-13 12:46:34 |
+-----+-----------------------+-----------------------+
and i want this output
| 3 | 2014-05-13 12:20:34 | 2014-05-13 12:46:34 |
because it has latest start_time_b from all timestamps
Referring to the SQL you posted, you can place that into a Django extra() Queryset modifier:
qs = YourModel.objects.extra(select={
'max_time': '''
select * from t where (
start_time_a in (
select greatest(max(start_time_a), max(start_time_b)) from t
) or start_time_b in (
select greatest(max(start_time_a), max(start_time_b)) from t
)
)'''
})
# each YourModel object in the queryset will have an extra attribute, max_time
for obj in qs:
print obj.max_time
For getting row of greatest value from two column I found this answer and it is quite usefull
select * from t where (
start_time_a in (select greatest(max(start_time_a), max(start_time_b)) from t) or
start_time_b in (select greatest(max(start_time_a), max(start_time_b)) from t)
);
mysql greatest() function
MySQL solution:
If you want to identify latest dates from all records, irrespective of other column values, you can use MAX function on the date columns.
Example:
select max( start_time_a ) as mx_start_time_a
, max( start_time_b ) as mx_start_time_b
from table_name

How to rewrite Raw SQL Query (MySQL) with Django ORM query?

How to rewrite next Raw SQL Query (MySQL) with Django ORM query?
mysql> select author_id,
count(*) c
from library_books
group by author_id
having c>2
limit 3;
+---------------+----+
| author_id | c |
+---------------+----+
| 0 | 39 |
| 1552 | 17 |
| 1784 | 8 |
+---------------+-----
First, annotate an author queryset with the number of books.
from django.db.models import Count
authors = Author.objects.annotate(num_books=Count('librarybook')
You haven't shown your Django models, so I've had to guess that 'librarybook' is the correct name for the reverse relationship.
Then filter on the num_books to find authors with more than two books.
authors = Author.objects.annotate(num_books=Count('librarybook').filter(num_books__gt=2)
Finally, slice the queryset to limit it to 3 results.
authors = Author.objects.annotate(num_books=Count('librarybook').filter(num_books__gt=2)[:3]
You can then loop through the resulting authors and access the number of books.
for author in authors:
print author.name, author.num_books

Django group by id then select max timestamp

It might be a redundant question, but I have tried previous answers from other related topics and still can't figure it out.
I have a table Board_status looks like this (multiple status and timestamp for each board):
time | board_id | status
-------------------------------
2012-4-5 | 1 | good
2013-6-6 | 1 | not good
2013-6-7 | 1 | alright
2012-6-8 | 2 | good
2012-6-4 | 3 | good
2012-6-10 | 2 | good
Now I want to select all records from Board_status table, group all of them by board_id for distinct board_id, then select the latest status on each board. Basically end up with table like this (only latest status and timestamp for each board):
time | board_id | status
------------------------------
2013-6-7 | 1 | alright
2012-6-4 | 3 | good
2012-6-10 | 2 | good
I have tried:
b = Board_status.objects.values('board_id').annotate(max=Max('time')).values_list('board_id','max','status')
but doesn't seem like it is working. Still give me more than 1 record per board_id.
Which command should I use in Django to do this?
An update, this is the solution I use. Not the best, but it works for now:
b=[]
a = Board_status.objects.values('board_id').distinct()
for i in range(a.count()):
b.append(Board_status.objects.filter(board_id=a[i]['board_id']).latest('time'))
So I got all board_id, store into list a. Then for each board_id, do another query to get the latest time. Any better answer is still welcomed.
How will it work? You neither have filter nor distinct to filter out the duplicates. I am not sure if this can be easily done in a single django query. You should read more on:
https://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.distinct
https://docs.djangoproject.com/en/1.4/topics/db/aggregation/
If you can't do it in 1 raw sql query, you can't do it with an OR mapper either as it's built on top of mysql (in your case). Can you tell me how you would do this via raw SQL?

Django ManyToMany relation add() error

I've got a model that looks like this,
class PL(models.Model):
locid = models.AutoField(primary_key=True)
mentionedby = models.ManyToManyField(PRT)
class PRT(models.Model):
tid = ..
The resulting many to many table in mysql is formed as,
+------------------+------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------------+------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| PL_id | int(11) | NO | MUL | NULL | |
| PRT_id | bigint(64) | NO | MUL | NULL | |
+------------------+------------+------+-----+---------+----------------+
Now, if pl is an object of PL and prt that of PRT, then doing
pl.mentionedby.add(prt)
gives me an error
Incorrect integer value: 'PRT object'
for column 'prt_id' at row 1"
whereas
pl.mentionedby.add(prt.tid)
works fine - with one caveat.
I can see all the elements in pl.mentionedby.all(), but I can't go to a mentioned PRT object and see its prt.mentionedby_set.all().
Does anyone know why this happens? Whats the best way to fix it?
Thanks!
Adding prt directly should work on first try. How are you retrieving pl and prt? Assuming you have some data in your database, try those commands from the Django shell and see if it works. There seems to be some missing information from the question. After running python manage.py shell:
from yourapp.models import PL
pl = PL.objects.get(id=1)
prt = PRT.objects.get(id=1)
pl.mentionedby.add(prt)
Are these the complete models? I can only assume that something's been overriden somewhere, that probably shouldn't have been.
Can you post the full code?

Categories

Resources