从每个关系中选择偶数项目

时间:2012-11-19 12:24:02

标签: django postgresql tastypie

我在我们的API中使用Tastypie,一个端点需要显示特定类别中的地点列表。 这部分很简单:

class PlaceResource(ModelResource):
    class Meta:
        queryset = Place.objects.all()
        filtering = { 
            'category': ALL
        }

但是我说我有一个limit = 100,我想从每个类别中获得偶数个位置。

示例:

/ API /地点/类别= 1和;类别= 2及类别= 3及类别= 4

应该从每个类别1,2,3和4给我25个位置。

我知道我可以使用SQL来做到这一点,但是如何以最佳方式完成?

1 个答案:

答案 0 :(得分:1)

说,我们有一张桌子:

CREATE TABLE place (
   place_id serial primary key
 , place    text
 , cat_id   int);

Test setup on sqlfiddle
您可以从category上的索引中获益,如设置中所示。

基本上,我看到两种不同的方式:

row_number()

WITH x AS (
    SELECT *, row_number() OVER (PARTITION BY category) AS rn
    FROM   place
    WHERE  category IN (1,2,3,4)
    )
SELECT place_id, place, category
FROM   x
ORDER  BY rn
LIMIT  100;
  • 除了相当优雅之外,这个查询变得越来越长的唯一部分是IN子句。
  • 无需计算自动发生的每个category的份额。
  • 如果某个类别的行数少于其共享的行数,则其余类别将以相等的份额填充其他类别。

UNION ALL

(SELECT * FROM place WHERE category = 1 LIMIT 25)
UNION ALL
(SELECT * FROM place WHERE category = 2 LIMIT 25)
UNION ALL
(SELECT * FROM place WHERE category = 3 LIMIT 25)
UNION ALL
(SELECT * FROM place WHERE category = 4 LIMIT 25);
  • 这是原始的,非常快,但对于许多类别来说都很长(虽然不慢)。
  • 使用UNION ALL,而不是UNION
  • 需要UNION查询的每一段的括号才能应用LIMIT
  • 您需要计算每个类别的份额,并决定如何拆分小数份额。
  • 如果某个类别的行数少于其共享的行数,则查询的行数会减少。