假设我有以下Django模型:
class Article(models.Model):
title = models.CharField(max_length=200)
blog = models.CharField(max_length=255)
rating = models.IntegerField(default=0)
class ArticleTag(models.Model):
article = models.ForeignKey(Article)
tag = models.CharField(max_length=200)
添加一些数据:
ArticleID Rating Blog
-----------------------------------------
article1 -> 1 3 CNN
article2 -> 2 2 BBC
article3 -> 3 5 BBC
article4 -> 4 9 NTV
ArticleID tag
-------------------
1 tag1
1 tag2
1 tag3
2 tag1
2 tag4
3 tag5
4 tag6
4 tag7
假设我们的用户喜欢tag1
,tag2
,tag6
和BBC
。所有文章都符合要求,因为第1条有tag1
和tag2
,第4条有tag1
,第2条和第3条来自BBC
。
如果我们按评分排序:article4
,article3
,article1
,article2
。
但是,我需要按照他们拥有的匹配标签数量+博客优先订购商品,然后按等级作为第二个订购参数。所以我希望结果按以下顺序排列:
tag1
和tag2
,评分= 3 tag1
和BBC
,评分= 2 tag6
,评分= 9 BBC
,评分= 5 是否可以在Django中执行此操作?如果没有,那么PostgreSQL呢?
答案 0 :(得分:1)
SQL查询可能如下所示:
SELECT *
FROM Article a
LEFT JOIN (
SELECT ArticleID, count(*) AS ct
FROM ArticleTag
WHERE tag IN ('tag1', 'tag2', 'tag6') -- your tags here
GROUP BY ArticleID
) t ON t.ArticleID = a.ID
ORDER BY t.ct DESC NULLS LAST
, (a.blog = 'BBC') DESC NULLS LAST -- your blog here
, rating DESC NULLS LAST;
基本上:
ArticleID
中按t
计算匹配的代码。LEFT JOIN
主要表格,包含辅助(blog
)和第三(rating
)排序条件的数据。ORDER BY
三个条件,ct
首先,blog
下一个,rating
最后一个。所有这些都下降(最高值第一)。这也适用于布尔表达式(a.blog = 'BBC')
,因为TRUE
(1)按降序排列FALSE
(0)之前。 重要事项:按降序排列NULL值会先排序,因此如果可以为NULL值,则需要NULLS LAST
(如果不能,则不会受到伤害) )。
即使您的所有列都已定义NOT NULL
,由于ct
,LEFT JOIN
仍然可以为NULL。
如果Django使用双引号保留混合大小写的名称,则必须在SQL中执行此操作。否则,所有标识符都将转换为小写。
答案 1 :(得分:1)
查询可能更简单我相信:) 这里没有真正需要加入。这是sqlfiddle:http://sqlfiddle.com/#!2/1e565/10
SELECT
article.ArticleID,
COUNT(DISTINCT tag.tag),
COUNT(DISTINCT article.Blog LIKE 'BBC'),
COUNT(DISTINCT tag.tag) + COUNT(DISTINCT article.Blog LIKE 'BBC'),
article.rating
FROM article
LEFT JOIN tag
ON tag.ArticleID = article.ArticleID
WHERE tag.tag IN ('tag1', 'tag2', 'tag6') OR article.Blog LIKE 'BBC'
GROUP BY
article.ArticleID,
article.rating
ORDER BY
COUNT(DISTINCT tag.tag) + COUNT(DISTINCT article.Blog LIKE 'BBC') DESC,
rating DESC