按两个值分组并获取第三个值



我有一个带有三个CharFields的Django模型,我想对它运行查询以获取其中两个的现有值,并为每个组合获取第三个字段的现有值。

    a = models.CharField(null=False, max_length=8000)
    b = models.CharField(null=False, max_length=8000)
    c = models.CharField(null=False, max_length=8000)

如果假定这些值在数据库中:

 a  | b  | c  |
---------------
 a1 | b2 | c3 |
 a1 | b2 | c1 |
 a2 | b2 | c3 |
 a1 | b3 | c3 |
 a1 | b2 | c2 |

我想要这种形式的一些结果:

{"a1-b2" : [c3, c1, c2], "a2-b2" : [c3], "a1-b3" : [c3]}
or 
{"a1" : {"b2":[c3, c1, c2], "b3": [c3]}, "a2": {"b2" : [c3]}} 

TLDR:

items = MyModel.objects.annotate(custom_field=Concat('a', Values('-'), 'b').values('custom_field', 'c')

解释

使用部分 .annotate(custom_field=Concat('a', Values('-'), 'b') ,您基本上是在 SQL 中执行group_by操作,并在查询集中创建一个名称为 custom_field 的临时新列,其值为 a-b

这为您提供了以下结构:

a    |    b    |    c    | custom_field
a1        b1        c1          a1-b1
a2        b2        c2          a2-b2 
a1        b1        c3          a1-b1

.values('custom_field', 'c')部分仅提取此查询集中的custom_field列和c列。现在您所要做的就是序列化数据。

编辑如果您希望数据采用该特定格式,则可以连接列c。请阅读这篇文章中 SO 接受的答案。Django 在模型中按另一个字段分组的字段列表。然后,您可以在序列化期间创建一个新字段,该字段会将串联的c字段split()到列表中。

想不出好的纯SQL解决方案,但这是使用groupby的pythonic解决方案:

from itertools import groupby
# Order by key fields so it will be easier to group later
items = YOUR_MODEL.objects.order_by('a', 'b')
# Group items by 'a' and 'b' fields as key
groups = groupby(items, lambda item: (item.a, item.b))
# Create dictionary with values as 'c' field from each item
res = {
    '-'.join(key): list(map(lambda item: item.c, group))
    for key, group in groups
}
# {'a1-b2': ['c3', 'c1', 'c2'], 'a1-b3': ['c3'], 'a2-b2': ['c3']}

相关内容

  • 没有找到相关文章

最新更新