views:

148

answers:

2

I have the field 'submission' which has a user and a problem. How can I get an SQL search result which will give a list of only one result per user-problem pair?

Models are like this:

class Problem(models.Model):
    title = models.CharField('Title', max_length = 100)
    question = models.TextField('Question')

class Submission(models.Model):
    user = models.ForeignKey(User)
    problem = models.ForeignKey(Problem)
    solution = models.CharKey()
    time = models.DateTimeField('Time', auto_now_add=True)
+2  A: 

Update 2:

(After reading OP's comments) I suggest adding a new model to track the latest submission. Call it LatestSubmission.

class LatestSubmission(models.Model):
    user = models.ForeignKey(User)     
    problem = models.ForeignKey(Problem)
    submission = models.ForeignKey(Submission)

You can then either

  1. override Submission.save() to create/update the entry in LatestSubmission every time an user posts a new solution for a Problem
  2. attach a function that does the same to a suitable signal.

such that LatestSubmission will contain one row per problem-user-submission combination pointing to the latest submission for the problem by each user. Once you have this in place you can fire a single query:

LatestSubmission.objects.all().order_by('problem')

Update:

Since the OP has posted sample code, the solution can now be changed as follows:

for user in User.objects.all(): # Get all users
    user.submission_set.latest('time') # Pick the latest submission based on time.

Original Answer

In the absence of any date/time based criteria for deciding which is "older" or "newer", you can use the primary key (id) of Submission to "neglect the old ones".

for user in User.objects.all(): # Get all users
    user.submission_set.latest('id') # Pick the latest submission by each user.
Manoj Govindan
I added the model details to my problem.This will give me only the query set of last submission by a user and what i want is the latest result for all the problems. I want to run a sql command on submission field and get the list of submissions ordered by submission time and will include only one result if there are more than one submissions by a same user in one problem.
dcrodjer
@Rohan Jain: I am not sure if you can do that with _one_ SQL query given your _current_ model structure. I'd like to know if anyone else here can come up with a suitable answer.
Manoj Govindan
i am doing this now by adding a is_latest boolean field for the submission.....thanx fr ur helps :)
dcrodjer
+1  A: 

Try this:

distinct_users_problems = Submission.objects.all().values("user", "problem").distinct()

It will give you a list of dicts like this one:

[{'problem': 1, 'user': 1}, {'problem': 2, 'user': 1}, {'problem': 3, 'user': 1}]

containing all the distinct pairs.

It actually results in your usual SELECT DISTINCT SQL query.

tkopczuk
hmm.....yeah i tried that...i actually resolved this by adding is_latest filed in submission....and will update it whenever a new submission of same problem is posted by a user....
dcrodjer