left join 右边没有值如何设置默认值

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了left join 右边没有值如何设置默认值相关的知识,希望对你有一定的参考价值。

数据库中用left join的时候如果右边的表里面没有值 请问如何设置默认值

参考技术A oracle:nvl(cols,defaultValue);mysql:ifnull(cols,defaultValue) 参考技术B 请先明确什么数据库 参考技术C 谁能回答呢?谢谢了

如何在 Django 1.9 中表达 sqlite LEFT OUTER JOIN?

【中文标题】如何在 Django 1.9 中表达 sqlite LEFT OUTER JOIN?【英文标题】:How to express a sqlite LEFT OUTER JOIN in Django 1.9? 【发布时间】:2016-05-04 10:24:32 【问题描述】:

我正在尝试为特定用户选择多个Content 对象及其相关的Vote 值,如果Content 对象没有该用户的相关Vote 值,则为“0” . (简化的)模型如下所示

class Content(models.Model):
    content_type = models.CharField(max_length=1, choices=choices, null=False)
    points = models.PositiveIntegerField(null=False, default=0)

class Vote(models.Model):
    user = models.ForeignKey(User, related_name='votes', null=False)
    content = models.ForeignKey(Content, related_name='votes', null=False)
    value = models.SmallIntegerField(null=False)  # either 1 or -1

这是 SQLite 中的一个简单的 LEFT OUTER JOIN,它将字段 is_upvoteis_downvote 附加到 Content 对象,具体取决于它找到的 Vote 值。

SELECT c.id, c.points, 
    COALESCE((v.value == 1), 0) AS is_upvote, 
    COALESCE((v.value == -1), 0) AS is_downvote 
FROM pgm4app_content c 
LEFT OUTER JOIN pgm4app_vote v ON v.content_id = c.id AND v.user_id=1 
WHERE c.content_type='q';

有没有办法在 Django 中表达这一点?我发现this answer from 3 years ago 建议进行两次单独的查找,然后在 Python 中加入。从那以后,Django ORM 是否发生了变化?

在 Python 中加入它看起来有点像这样

c = Content.objects.filter(content_type='q')
v = obj.user_id: obj.value for obj in Vote.objects.filter(user=1, content__in=c)
for obj in c:
    obj.is_upvote = v.get(obj.id, 0) == 1
    obj.is_downvote = v.get(obj.id, 0) == -1

【问题讨论】:

你将在哪里使用输出?在寺庙里? 是的,也可能在视图中。但我也出于好奇而问,因为我没有成功在 Django ORM 中表达这一点,看看是否有可能。 我正在考虑在获取所有记录后应用过滤器。这也可以在模板和视图中完成。 既然您已经有了查询,只需发送到 raw。 【参考方案1】:

是的!您可以在较新版本的 Django 中通过 ORM 执行此操作 - 请参阅 documentation on conditional expressions:

from django.db.models import IntegerField, Case, When, Sum, Q

Content.objects.all().annotate(
    num_votes=Sum(Case(
            When(Q(votes__user__pk=1) & Q(votes__value=1), then=1),
            When(Q(votes__user__pk=1) & Q(votes__value=-1), then=-1),
            default=0,
            output_field=IntegerField()
            )
        )
    )

生成的 SQL 查询类似于:

SELECT "myapp_content"."id", "myapp_content"."points", 
SUM(CASE WHEN ("myapp_vote"."user_id" = 1 AND "myapp_vote"."value" = 1) THEN 1 
WHEN ("myapp_vote"."user_id" = 1 AND "myapp_vote"."value" = -1) THEN -1 ELSE 0 END) 
AS "num_votes" FROM "myapp_content" 
LEFT OUTER JOIN "myapp_vote" ON ("myapp_content"."id" = "myapp_vote"."content_id") 
GROUP BY "myapp_content"."id", "myapp_content"."points"

这不是两个属性is_upvoteis_downvote,而是返回一个属性num_votes,它是01-1,具体取决于用户的投票方式。这可以在 Python 中轻松转换为两个属性。

(我确信一定可以在数据库中生成两个属性,但我的第一次尝试失败了!)。

【讨论】:

太棒了,我之前在Case(When()) 上玩过,但还没到那里。 但是,上面的查询还不能正常工作。它返回多个Content 对象的实例,每个相关的Vote 对象都有一个实例,似乎忽略了votes__user__pk 限制。 @C14L 我已经编辑了答案以采取不同的方法(我有理由确定)有效并且不提供重复项。以前的方法确实返回多行。

以上是关于left join 右边没有值如何设置默认值的主要内容,如果未能解决你的问题,请参考以下文章

从 LEFT JOIN 设置 NULL 列的默认值并使用 WHERE 过滤

Oracle left join 或right join

背景图设置

如何获取默认的系统填充值?

默认的body margin,我没有设置,但它确实有默认值8px,如何获取这个值?

如何在没有重复的情况下在 hive 中执行 LEFT OUTER JOIN 以仅检查右表中的一个值?