如何使用Django ORM创建交叉表SQL查询?

时间:2009-12-07 10:06:48

标签: sql django orm

使用Django 1.1,如何使用ORM创建交叉表(数据透视表)SQL查询?

更新: 这些是模型和输出要求:

class Store(models.Model):
    name = models.CharField(max_length=255)
    ...

class Order(models.Model):
    store = models.ForeignKey(Store, blank=True, null=True, related_name='orders')
    description = models.CharField(_('Description'), max_length=255)
    quantity = models.IntegerField(blank=True, null=True)       
    type_detail = models.CharField(_('Type Detail'), max_length=255)
    slug = models.SlugField(blank=True)
    cost = models.DecimalField(_("Cost"), max_digits=14, decimal_places=2)
    modified = models.DateTimeField(_('modified'), auto_now=True)

目前该视图显示如下数据:

Store   | Type Detail  | Quantity 
----------------------------------
Walmart | Floor polish | 2        
Walmart | Tiles        | 1        
Walmart | Milk         | 4      
Another | Floor polish | 2        
Another | Tiles        | 1        
Another | Milk         | 4        

我想透视它来查看数据,如下所示:

对于商店我需要知道数量

Store   | Floor polish  | Tiles | Milk
------------------------------------------------
Walmart | 2             | 1     | 4
Another | 2             | 1     | 4

我希望这能解释我的需要。

3 个答案:

答案 0 :(得分:3)

您可以在模板中执行以下操作(假设您将line_items传递给模板,并假设store.name是唯一属性):

{% regroup line_items by store.name as store_items %}
{% for store in store_items %}    
  <tr>
    <td>{{ store.grouper }}</td>
    {% for item in store.list %}
      <td>{{ item.count }}</td>
    {% endfor %}
  </tr>
{% endfor %}

如果所有商店都有相同的库存,这将有效,否则您需要填补视图中的空白(例如,对于缺少的库存商品,返回0)

答案 1 :(得分:2)

正确的交叉表需要每个维度成员的值。这是我编造的东西(见下文)。您可以在Django模板中使用它,就像在doctext示例中一样。因此,您将发出1)所有商店值,2)所有type_detail值和3)每个商店的数量和type_detail的查询。然后第三个查询的结果进入(store,type)=&gt;的字典中。量。

class Cube(object):
    """Iterable sparse cube. Iterating gives an item for every dimension member.

    >>> pythons = ['eric', 'john', 'terry']
    >>> cheeses = ['limburg', 'feta', 'parmigiano']
    >>> cheese_consumption = {
        ('eric', 'limburg'): 2,
        ('eric', 'parmigiano'): 4,
        ('john', 'feta'): 5
    }
    >>> cheese_cube = Cube((pythons, cheeses), cheese_consumption)
    >>> for python, python_cheeses in cheese_cube:
        for cheese, consumption in python_cheeses:
            print python, cheese, consumption or 0

    eric limburg 2
    eric feta 0
    eric parmigiano 4
    john limburg 0
    john feta 5 
    john parmigiano 0
    terry limburg 0
    terry feta 0
    terry parmigiano 0
    """
    def __init__(self, dimensions, facts, slice=None):
        self.dimensions = dimensions
        self.data_dict = facts
        self.slice = slice or ()
    def __iter__(self):
        if len(self.slice) + 1 < len(self.dimensions):
            for item in self.dimensions[len(self.slice)]:
                yield item, Cube(self.dimensions, self.data_dict, self.slice + (item,))
        else:
            for item in self.dimensions[len(self.slice)]:
                yield item, self.data_dict.get(self.slice + (item,), None)

答案 2 :(得分:-1)

不知道Django,但这里是简单的SQL

SELECT Store,
SUM(CASE WHEN Type_Detail = 'Floor polish' THEN Quantity ELSE 0 END) as 'Floor polish',
SUM(CASE WHEN Type_Detail = 'Tiles' THEN Quantity ELSE 0 END) as 'Tiles',
SUM(CASE WHEN Type_Detail = 'Milk' THEN Quantity ELSE 0 END) as 'Milk'
FROM Order
GROUP BY Store