我有模特:
class A(models.Model):
pass
class B(models.model):
a = models.ForeighKey(A)
name = models.CharField()
value = models.CharField()
我需要获取A的X个(例如X = 10),如果B.name =='name1',则按B.value过滤,如果B.name =='name2',则按B.value排序仅使用Django ORM。
我想要的SQL是这样的:
SELECT table_a.id
FROM table_a
INNER JOIN table_b ON (table_a.id = table_b.a_id)
LEFT OUTER JOIN (
SELECT table_a.id as id, table_b.value as value
FROM table_a
INNER JOIN table_b ON (table_a.id = table_b.a_id)
WHERE table_b.name = 'name2'
GROUP BY table_a.id
) tmp_table ON (tmp_table.id = table_a.id)
WHERE (table_b.name = 'name1' AND table_b.value::text LIKE '%mid%')
GROUP BY table_a.id
ORDER BY tmp_table.value
LIMIT 10;
对于A的每个项目,B.name的值都是唯一的(这就是我使用INNER JOIN的原因)。
我知道的最简单的方法是:
# Filtering A
a_set = dict((a.id, {'b': {}}) for a in A.objects.filter(b__name='name1', b__value__contains='mid'))
# I just need to know all b-items for a_set
# "a_id__in=<huge list>" is bad idea, so I want to paginate a_set before it
for b in B.objects.filter(a_id__in=a_set):
a_set[b.a_id]['b'][b.name] = b.value
# Sorting where items of A without 'name2' will be at the end
sorted_ids = list(x[1] for x in sorted(
(a_set[a_id]['b'].get('name2', 'zzz'), a_id) for a_id in a_set
))
# Pagination
sorted_ids = sorted_ids[:10]
但是我需要针对有很多A项的情况进行优化。