【问题标题】:group by two values and get the third values按两个值分组并获得第三个值
【发布时间】:2019-11-23 05:22:52
【问题描述】:

我有这个带有三个 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]}} 

【问题讨论】:

    标签: django django-orm


    【解决方案1】:

    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_fieldc 列。现在您所要做的就是序列化您的数据。

    编辑 如果您希望数据采用该特定格式,您可以连接列c。请阅读这篇文章中接受的答案。 Django making a list of a field grouping by another field in model。然后,您可以在序列化期间创建一个新字段,它将split() 连接的c 字段放入一个列表中。

    【讨论】:

      【解决方案2】:

      想不出好的纯 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']}
      

      【讨论】:

        猜你喜欢
        • 2021-12-04
        • 2018-11-29
        • 1970-01-01
        • 1970-01-01
        • 2020-02-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多