Python 选择具有匹配标记的所有项目
假设我有以下Django模型:Python 选择具有匹配标记的所有项目,python,sql,django,postgresql,sql-order-by,Python,Sql,Django,Postgresql,Sql Order By,假设我有以下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
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的用户。所有文章都符合要求,因为第一条有tag1和tag2,第四条有tag1,第二条和第三条来自BBC
如果我们按等级排序:第4条、第3条、第1条、第2条
但是,我首先需要根据匹配标记的数量+blog对项目进行排序,然后将其作为第二个排序参数进行评级。因此,我希望结果按以下顺序排列:
第1条-tag1和tag2,评级=3
第2条-tag1和BBC,评级=2
第4条-tag6,评级=9
第3条——英国广播公司,评级=5
在Django可以这样做吗?如果不是,那么PostgreSQL呢 SQL查询可能如下所示: 挑选* 来自a条 左连接 选择ArticleID,将*计为ct 来自ArticleTag 标签在“tag1”、“tag2”、“tag6”中的位置-您的标签在此处 按项目分组ID t ON t.ArticleID=a.ID 按t.ct描述的订单最后为空 ,a.blog='BBC'DESC NULLS LAST-您的博客在此 ,最后的额定值为空; 基本上: 计算子查询t中每个ArticleID的匹配标记。 左键将主表与第二个博客和第三个评级排序标准的数据连接起来。 按三个标准排序,ct第一,博客第二,评级最后。它们都是先降最高值。这也适用于布尔表达式a.blog='BBC',因为TRUE 1按降序排列在FALSE 0之前。 重要提示:按降序,空值将首先排序,因此如果可能存在空值,则需要最后为空,如果不存在空值,则不会有任何影响 即使所有列都定义为NOTNULL,由于左连接,ct仍然可以为NULL
如果Django使用双引号保留混合大小写名称,那么您也必须在SQL中这样做。否则,所有标识符都转换为小写。我认为查询可能更简单: 这里真的不需要加入。下面是sqlfiddle:
你的数据类型是什么?项目1、评级和标签?@Kasra谢谢,我已经更新了问题请添加Django模型定义:@Wolph我已经更新了问题。非常感谢。这个问题解释得很清楚,这使问题以一种积极的方式突出。添加您的Postgres和Django版本也不是一个坏主意。谢谢!你能解释一下为什么这样更好,因为你也有一个连接吗?计数也有一些问题,它为标记和博客显示相同的值。@nickbusted:连接通常更容易为数据库优化,所以我通常更喜欢避免子查询。至于计数问题。。。我忘了给那些加一个不同的。现在修复它:
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