On Fri, Mar 12, 2010 at 5:54 PM, jrs <j...@framemedia.com> wrote:

> I'm trying, without a great deal of success, to perform a simple self
> join using the django orm.  I'm pretty sure the F() function is not
> the answer.  I believe this only allows you to compare two field
> within the same model instance, not to compare fields within 2
> instances of the same model.  I want to do this -
>
> Model-
>
> class Account(models.Model):
>    name = models.CharField(max_length=255)
>    parent_account = models.ForeignKey('self', default=None, blank=True)
>

First, you are going to need a null=True on that parent_account field.
Without it an attempt to save an Account with parent_account=None is going
to raise an IntegrityError.


> SQL-
>
> SELECT account.*, parent.*
> FROM account
> LEFT JOIN account parent ON
>   account.id = parent.parent_account
>
>
What are you trying to accomplish with this SQL? Given an account table
with:

mysql> select * from account;
+----+------+-------------------+
| id | name | parent_account_id |
+----+------+-------------------+
|  1 | A1   |                 1 |
|  2 | A2   |              NULL |
|  3 | A3   |                 2 |
|  4 | A4   |                 2 |
+----+------+-------------------+
4 rows in set (0.00 sec)

The query you show returns:

mysql> select account.*, parent.* from account left join account parent on
account.id = parent.parent_account_id;
+----+------+-------------------+------+------+-------------------+
| id | name | parent_account_id | id   | name | parent_account_id |
+----+------+-------------------+------+------+-------------------+
|  1 | A1   |                 1 |    1 | A1   |                 1 |
|  2 | A2   |              NULL |    3 | A3   |                 2 |
|  2 | A2   |              NULL |    4 | A4   |                 2 |
|  3 | A3   |                 2 | NULL | NULL |              NULL |
|  4 | A4   |                 2 | NULL | NULL |              NULL |
+----+------+-------------------+------+------+-------------------+
5 rows in set (0.00 sec)

The right-side columns coming from the 'parent' table in that result would
more appropriately be labeled 'child', I think, so I'm not entirely sure
this query is doing what you wanted.

It is possible to get the Django ORM to issue a query that seems to match
the intent of how you named those tables in your query, via
Account.objects.select_related('parent_account'). You can check the sql in a
shell:

>>> from ttt.models import Account
>>> from django.db import connection
>>> Account.objects.select_related('parent_account')
[<Account: A1 (Parent: 1))>, <Account: A2 (No parent))>, <Account: A3
(Parent: 2))>, <Account: A4 (Parent: 2))>]
>>> len(connection.queries)
1
>>> connection.queries[-1]['sql']
u'SELECT `account`.`id`, `account`.`name`, `account`.`parent_account_id`,
T2.`id`, T2.`name`, T2.`parent_account_id` FROM `account` LEFT OUTER JOIN
`account` T2 ON (`account`.`parent_account_id` = T2.`id`) LIMIT 21'
>>>

The actual results of that query are:

mysql> select account.*, T2.* from account left outer join account T2 on
account.parent_account_id = T2.id;
+----+------+-------------------+------+------+-------------------+
| id | name | parent_account_id | id   | name | parent_account_id |
+----+------+-------------------+------+------+-------------------+
|  1 | A1   |                 1 |    1 | A1   |                 1 |
|  2 | A2   |              NULL | NULL | NULL |              NULL |
|  3 | A3   |                 2 |    2 | A2   |              NULL |
|  4 | A4   |                 2 |    2 | A2   |              NULL |
+----+------+-------------------+------+------+-------------------+
4 rows in set (0.00 sec)

Those results seem to better match what your query was intended to produce
given how you named the alias, where the right-side columns have information
about the left-side's parent. Or were you really looking for the results of
the original query?

If you described what you were looking for in terms of the Account objects,
someone might be able to help more.

Karen

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-us...@googlegroups.com.
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en.

Reply via email to