左边加入Django模型查询?

时间:2018-03-09 06:44:21

标签: mysql django django-queryset

我想在django模型查询中使用mysql查询的左连接。

我想要使用的mysql查询是:

select U.id, B.id as boardId, count(BJ.id) as countBoardMember,
       count(NM.id) as newsCountInBaord
from users as U
left join boards as B on B.userId = U.id
left join board_join as BJ on B.id = BJ.boardId
left join news_mappings as NM on NM.boardId = B.id
where B.isArchived = false
group by B.id
having countBoardMember < 10 and newsCountInBaord < 5
limit 10

但Django模型查询正在使用左外连接然后内连接:

SELECT `users`.`id`, COUNT(`board_join`.`joinedBy`) AS `countBoardMember`,
       COUNT(`news_mappings`.`id`) AS `newsCountInBaord`
FROM `users`
LEFT OUTER JOIN `boards` ON (`users`.`id` = `boards`.`userId`)
LEFT OUTER JOIN `board_join` ON (`boards`.`id` = `board_join`.`boardId`)
LEFT OUTER JOIN `news_mappings` ON (`boards`.`id` = `news_mappings`.`boardId`)
INNER JOIN `boards` T6 ON (`users`.`id` = T6.`userId`)
INNER JOIN `board_join` T7 ON (T6.`id` = T7.`boardId`)
WHERE (T7.`requestStatus` = approved AND T6.`isArchived` = False)
GROUP BY `users`.`id`
HAVING (COUNT(`board_join`.`joinedBy`) > 10 AND COUNT(`news_mappings`.`id`) > 5)
ORDER BY NULL limit 10;

实现结果需要更长的时间。

我的django模型查询是这样的:

user_ids = (
    Users.objects.using('cms')
    .annotate(countBoardMember=Count('boards__boardjoin__joinedBy'),
              newsCountInBaord=Count('boards__newsmappings__id'))
    .filter(boards__isArchived=0, boards__boardjoin__requestStatus='approved', 
            countBoardMember__gt=10, newsCountInBaord__gt=5).all()
)

我在Django模型查询中出错了什么?

1 个答案:

答案 0 :(得分:0)

创建外部联接是因为字段“ newsmappings”,“ joinedBy”和“ boardjoin”可能为空。

您可以执行以下任一操作:

  1. 在模型板,board_join,news_mappings中将“ null = True”删除到thees字段不能为空
  2. 向查询添加过滤器以排除空条目。例如:

    user_ids = (
    Users.objects.using('cms')
    .annotate(countBoardMember=Count('boards__boardjoin__joinedBy'),
              newsCountInBaord=Count('boards__newsmappings__id'))
    .filter(boards__isArchived=0, boards__boardjoin__requestStatus='approved', 
            countBoardMember__gt=10, newsCountInBaord__gt=5,
            boards__isnull=False, boards__boardjoin__isnull=False,
            boards__newsmappings__isnull=False).all()
    )