How to get the last 3 created objects from the database? - html

I want to display the last 3 created objects onto my website. I have no clue what to do.
I just need to know how to order the model according to created date. And, access the 1st, 2nd and 3rd item of the ordered set.
I'm pretty sure this doesn't work. This is from views.py
latest = Upcoming_Events.objects.all().order_by('date')[:3]
event1 = latest.get(pk=1)
event2 = latest.get(pk=2)
event3 = latest.get(pk=3)
I keep getting
'Cannot filter a query once a slice has been taken'

You can make ORM like this
latest = Upcoming_Events.objects.all().order_by('-date')[:3]
Then in template
{% for event in latest %}
{{ event.date }}
{% endfor %}
Update:
As per comment try this
event1 = latest[0]
event2 = latest[1]
event3 = latest[2]

make a descending order on pk(id)
latest = Upcoming_Events.objects.all().values().order_by('-id')[:3]
then:
event1 = latest[0]
UPDATE
Notice that you have to use .values().
If you do not use it the SQL Query will not contain LIMIT 3

Related

Spring data JPA repository order by condition

I have a Product entity which contains some attributes, I need to get the closest products to a given product depending on some criteria, the criteria are category, finish and production company.
I wrote this query
#Query("Select pr from Product pr ORDER BY (CASE WHEN (pr.category = :p.category) THEN 1 WHEN (pr.finish = :p.finish) THEN 2 WHEN (pr.productionCompany = :p.productionCompany) THEN 3 ELSE 4 ) LIMIT 5")
List<Product> findRecommendedProducts(#Param("p")Product p);
But this keeps giving me the following exception
antlr.MismatchedTokenException: expecting "end", found ')'
Any help is appreciated.
I think you need to add ELSE 4 END to your query. I assume this is running on Oracle?

Mysql query in django view

I do not have much knowledge of mysql. My django model is as follows:
class Exercise_state(models.Model):
exercise = models.ForeignKey(Exercise, blank=True, null=True)
user = models.ForeignKey(User, blank=True, null=True)
intensity_level = models.IntegerField(default='1')
progress = models.IntegerField(default='0')
current_date = models.DateField(auto_now=True)
user_rating = models.IntegerField(default='0')
I want to retrieve count of user_id's which satisfy exercise_id=1 corresponding intensity_level=7 and so on for all exercise_id's till 7. In short, users who have reached intensity_level=7 in all the exercises.
I have written one query which is as follows:
select count(user_id) from demo_exercise_state where
exercise_id=1 and intensity_level=7 and
exercise_id=2 and intensity_level=7 and
exercise_id=3 and intensity_level=7 and
exercise_id=4 and intensity_level=7 and
exercise_id=5 and intensity_level=7 and
exercise_id=6 and intensity_level=7 and
exercise_id=7 and intensity_level=7;
As far as I can cross check results from my database directly no user has yet completed his training (i.e. who has reached intensity_level=7 in all exercise types), so it returns the count as '0'.
I am sure this can query be optimized as there is quite much repeatation, but I am not sure how.
Also I want to execute the same (i.e. get the same result) in my django view. There I have something like
all_exercise_finish_count = Exercise_state.objects.filter(exercise_id=1, intensity_level=7).count()
How can I reflect the same in this django view?
Update
Completely changing my answer because the subsequent discussion in the comment made it clear that the OPs intentions were quite different from what it first appeared to be.
You can find the users who have completed all the 7 excercises at intensity 7 in the following way
from django.db.models.import Count
Exercise_state.objects.annotate(
c = Count('exercise').filter(c=7, exercise_id= 7)
First form of the answer is below:
The original raw query can be greatly simplified with between
expr BETWEEN min AND max
If expr is greater than or equal to min and expr is less than or equal
to max, BETWEEN returns 1, otherwise it returns 0. This is equivalent
to the expression (min <= expr AND expr <= max) if all the arguments
are of the same type. Otherwise type conversion takes place according
to the rules described in Section 13.2, “Type Conversion in Expression
Evaluation”, but applied to all the three arguments.
select count(user_id) from demo_exercise_state where
exercise_id BETWEEN 1 and 7 AND intensity_level=7
And the django query can simply be
all_exercise_finish_count = Exercise_state.objects.filter(exercise_id__gte=1, intensity_level=7, excercise_id__lte=7).count()

Can SQL query do this?

I have a table "audit" with a "description" column, a "record_id" column and a "record_date" column. I want to select only those records where the description matches one of two possible strings (say, LIKE "NEW%" OR LIKE "ARCH%") where the record_id in each of those two matches each other. I then need to calculate the difference in days between the record_date of each other.
For instance, my table may contain:
id description record_id record_date
1 New Sub 1000 04/14/13
2 Mod 1000 04/14/13
3 Archived 1000 04/15/13
4 New Sub 1001 04/13/13
I would want to select only rows 1 and 3 and then calculate the number of days between 4/15 and 4/14 to determine how long it took to go from New to Archived for that record (1000). Both a New and an Archived entry must be present for any record for it to be counted (I don't care about ones that haven't been archived). Does this make sense and is it possible to calculate this in a SQL query? I don't know much beyond basic SQL.
I am using MySQL Workbench to do this.
The following is untested, but it should work asuming that any given record_id can only show up once with "New Sub" and "Archived"
select n.id as new_id
,a.id as archive_id
,record_id
,n.record_date as new_date
,a.record_date as archive_date
,DateDiff(a.record_date, n.record_date) as days_between
from audit n
join audit a using(record_id)
where n.description = 'New Sub'
and a.description = 'Archieved';
I changed from OR to AND, because I thought you wanted only the nr of days between records that was actually archived.
My test was in SQL Server so the syntax might need to be tweaked slightly for your (especially the DATEDIFF function) but you can select from the same table twice, one side grabbing the 'new' and one grabbing the 'archived' then linking them by record_id...
SELECT
newsub.id,
newsub.description,
newsub.record_date,
arc.id,
arc.description,
arc.record_date,
DATEDIFF(day, newsub.record_date, arc.record_date) AS DaysBetween
FROM
foo1 arc
, foo1 newsub
WHERE
(newsub.description LIKE 'NEW%')
AND
(arc.description LIKE 'ARC%')
AND
(newsub.record_id = arc.record_id)

MySQL query for sorting comments and their nested replies

I have read over 10 related posts here and elsewhere and still can't figure this one out, being rather new to php and MySQL:
I am using WordPress and trying to implement nested comments within an old theme. My table is all set (let's call it 'comments') and has the following fields:
comment_ID | comment_date | comment_parent, etc.
comment_parent remains equal to 0 in top level comments; it is equal to the comment_ID of the comment replied to in nested replies.
The original MySQL query looks like this:
SELECT * FROM $wpdb->comments
WHERE comment_post_ID = %d AND comment_approved = '1'
ORDER BY comment_date ASC LIMIT %d"
Through the php that follows and outputs the comment list, comments are listed by date without respecting nested replies as such:
comment_ID | comment_date | comment_parent
100 Jan 01 0 (this is a top level comment)
104 Jan 03 0 (this is a top level comment)
106 Jan 04 100 (this is a reply to the first comment)
108 Jan 05 104 (this is a reply to the second comment)
Obviously, the sequence is broken since I am sorting by date. Comment 106 should appear right below comment 100, and comment 108 should be below comment 104.
I am trying not to change my php and I would like to do this with the MySQL query but can't get it right. I have tried using JOIN, GROUP BY, HAVING as suggested in similar questions, without any success. Is there a way for me to achieve the correct sorting right from the query and keep my php intact?
Well, I've finally figured it out, thanks partially to Nupul's comment above who said that: "You can first fetch all the top level comments in one go and then the nested comments (all) in the second round and populate your content accordingly.". I had indeed tried that option unsuccessfully, but this motivated me to persevere...
For the record and hoping that this can help someone in the future, here's how I've fixed it. Two separate MySQL queries fetching first the top level comments and second, the nested comment replies (these queries are formatted for WordPress.)
$comments = $wpdb->get_results($wpdb->prepare("
SELECT *
FROM $wpdb->comments
WHERE comment_post_ID = %d AND comment_approved = '1' AND comment_parent = '0'
ORDER BY comment_date ASC
LIMIT %d
",etc,etc));
$replies = $wpdb->get_results($wpdb->prepare("
SELECT *
FROM $wpdb->comments
WHERE comment_post_ID = %d AND comment_approved = '1' AND comment_parent <> '0'
ORDER BY comment_date ASC
LIMIT %d
",etc,etc));
Then I go into my main comment loop (FOREACH) looking for top level comments only. Within that loop, at the bottom, I jump into a nested IF loop looking for nested comments where
$reply->comment_parent == $comment->comment_ID (comparing my 2 MySQL queries)
and if true adjusting $comments to equal $replies so that my nested comments are echoed correctly by WordPress. I then return the value of $comments to its original and exit my nested comment loop back to the main FOREACH.
There are probably flaws in my reasoning or execution but it works like a charm! Of course this does not provide for additional nested levels and all nested comments are written one after the other even if they are replies to each other, but that's good enough for me!
For a demo, http://www.vincentmounier.com/blog2/ and click on any of the "Show Comments" links at the the bottom of posts. Nupul, thanks again for the motivation!
You may be better off changing your table design. One of the better ways to implement nested comments is with Modified Preorder Tree Traversal (MPTT)
This is an article about an MPTT menu, but you should be able to learn how to implement a comment system using a similar scheme.

Optimise Linq-to-Sql mapping with one to many lookup

I'm having problems optimising data lookup with the following data structure:
Order
-----
Id
Customer
Date
... etc
OrderStatus
------
Id
OrderId
Date
UpdatedBy
StatusTypeId
...etc
This is causing me a headache on the Order List page, which basically shows a list of Orders. Each Order Summary in the list shows a bunch of fields from Order and the current OrderStatus, i.e. the OrderStatus with the latest Date which is linked to the Order.
Order List
-------------------------------------------------------
Order Id | Customer | Order Date | CurrentStatus |
-------------------------------------------------------
1 | Someone | 1.10.2010 | Completed |
-------------------------------------------------------
2 | Someone else | 12.10.2010 | In Progress |
-------------------------------------------------------
3 | Whoever | 17.10.2010 | On Hold |
-------------------------------------------------------
Now, say I want to list all orders from this year. My Repository fetches the Order objects
var orders = _repository.GetAllOrdersSinceDate(dt);
and now I end up with something like
foreach (Order order in orders)
{
OrderSummary summary = new OrderSummary();
summary.Customer = order.Customer;
summary.Date = order.Date;
// ...etc
// problem here!!
summary.OrderStatus = order.OrderStatus
.OrderByDescending(s => status.Date).First();
}
So what I end up with is a SELECT statement on Order and then a further SELECT statement on OrderStatus for each Order returned.
So to show the summary of all records for this year is requiring around 20,000 individual SQL queries and taking many minutes to load.
Is there any neat way to fix this problem?
I'm considering re-writing the database to hold the current OrderStatus in the Order table, so I end up with something like
Order
-----
Id
Customer
Date
CurrentStatusTypeId
CurrentStatusDate
CurrentStatusUpdatedBy
...etc
OrderStatusHistory
------
Id
OrderId
Date
UpdatedBy
StatusTypeId
...etc
which is the only way I can see to solve the problem but seems a pretty nasty solution.
Whats the best way forward here?
Please don't denormalize your database model to solve your problem. This will only make things worse. You can fix this by writing a service method that returns a list of data transfer objects (DTO) instead of the LINQ to SQL entities. For instance, the service method might look like this:
public OrderSummary[] GetOrderSummariesSinceDate(DateTime d)
{
return (
from order in this.context.Orders
where order.Date >= d
let lastStatus = (
from status in order.OrderStatusses
orderby status.Date descending
select status).First()
select new OrderSummary
{
OrderId = order.Id,
CustomerName = order.Customer.Name,
Date = order.Date,
OrderStatus = lastStatus.StatusType.Name
}).ToArray();
}
Note the following:
This code will execute as a single SQL query in the database.
This method will return an object that contains just the data that the client needs, but nothing more. No Customer object, no OrderStatus object.
By calling ToArray we ensure that the database is queried at this point and it is not deferred.
These three points ensure that the performance is maximized and allows the service layer to stay in control over what is executed to the database.
I hope this helps.
You can create a DataLoadOptions object as follows:
DataContext db = new DataContext
DataLoadOptions ds = new DataLoadOptions();
ds.LoadWith<OrderStatus>(c => c.Orders);
db.LoadOptions = ds;
Then when you run your query it should prefetch the OrderStatus table