Django ORM left join subquery
У меня следующая модель:
class Transaction(models.Model):
created_by_id = models.IntegerField()
quantity = models.FloatField()
transaction_type = models.SmalIntegerField()
transaction_status = models.SmallIntegerField()
related_transaction_id = models.IntegerField(
blank=True,
null=True,
)
В настоящее время в таблице хранятся следующие данные:
id | created_by_id | quantity | transaction_type | transaction_status | related_transaction_id |
---|---|---|---|---|---|
27 | 25 | 1 | 2 | 3 | 24 |
26 | 25 | 0 | 2 | 1 | 25 |
25 | 10 | -1 | 2 | 2 | null |
24 | 10 | -1 | 2 | 2 | null |
23 | 10 | -1 | 2 | 2 | null |
22 | 10 | -1 | 2 | 2 | null |
21 | 25 | 1 | 1 | 1 | null |
Я хочу воспроизвести следующий SQL оператор в ORM Django (это точный вывод, который я ищу):
WITH pending_status AS (
SELECT
id AS pending_id,
transaction_status AS pending_status
FROM transaction
WHERE transaction_status = 2
),
done_or_rejected AS (
SELECT
id AS related_id,
related_transaction_id,
transaction_status AS current_status
FROM transaction
WHERE transaction_status != 2
AND transaction_type = 2
),
all_transactions AS (
SELECT
id AS original_id,
created_by_id,
quantity,
transaction_status,
transaction_type
FROM transaction
)
SELECT
original_id,
created_by_id,
quantity,
related_id,
coalesce(current_status, transaction_status) as status,
transaction_type
FROM all_transactions
LEFT JOIN pending_status
ON pending_status.pending_id = all_transactions.original_id
LEFT JOIN done_or_rejected
ON done_or_rejected.related_transaction_id = pending_status.pending_id
AND pending_status.pending_status != done_or_rejected.current_status
WHERE
(related_id IS NULL AND transaction_status = 1 AND transaction_type != 2)
OR (related_id IS NULL AND transaction_status = 2 AND transaction_type = 2)
OR (related_id IS NOT NULL)
ORDER BY original_id DESC;
Который возвращает следующий вывод:
original_id | created_by_id | quantity | related_id | status | transaction_type |
---|---|---|---|---|---|
25 | 10 | -1 | 26 | 1 | 2 |
24 | 10 | -1 | 27 | 3 | 2 |
23 | 10 | -1 | null | 2 | 2 |
22 | 10 | -1 | null | 2 | 2 |
21 | 25 | 1 | null | 1 | 1 |
Эти три подзапроса я продублировал следующим образом:
pending_status = (
Transaction
.objects
.filter(transaction_status=2)
.values(
pending_id=models.F("id"),
pending_status=models.F("transaction_status"),
)
)
done_or_rejected = (
Transaction
.objects
.filter(~models.Q(transaction_status=2))
.filter(transaction_type=2)
.values(
"related_transaction_id",
related_id=models.F("id"),
current_status=models.F("transaction_status"),
)
)
all_transactions = (
Transaction
.objects
.values(
"created_by_id",
"quantity",
"transaction_status",
"transaction_type",
original_id=models.F("id"),
)
)
Есть ли способ сделать два левых соединения на двух разных подзапросах? Как я могу перевести этот SQL-запрос в ORM Django?
Спасибо!