Python 选择具有匹配标记的所有项目

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

假设我有以下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的用户。所有文章都符合要求,因为第一条有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