【问题标题】:How would I avoid using two separate queries for this purpose?我将如何避免为此目的使用两个单独的查询?
【发布时间】:2014-11-02 09:46:51
【问题描述】:

我正在使用 MySQL 创建文章和类别的数据库。每篇文章都有一个类别。我想为管理面板创建一个功能,列出所有类别,但还包括每个类别的最新文章。我通常使用的方法是从类别表中获取行,遍历结果,然后使用FROM articlesWHERE category_id = {CATEGORY_ID} ORDER BY article_id DESC LIMIT 1 之类的东西创建另一个查询。这种方法看起来有点过头了我和我想知道它是否可以在一个查询中完成(也许使用连接和子查询?)。

这是我获取类别的当前查询:

SELECT * FROM article_categories ORDER BY category_title ASC

这些是我的桌子:

CREATE TABLE IF NOT EXISTS `articles` (
  `article_id` int(15) NOT NULL AUTO_INCREMENT,
  `author_id` int(15) NOT NULL,
  `category_id` int(15) NOT NULL,
  `modification_id` int(15) NOT NULL,
  `title` varchar(125) NOT NULL,
  `content` text NOT NULL,
  `type` tinyint(1) NOT NULL,
  `date_posted` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `status` tinyint(1) NOT NULL,
  `attachment_id` int(15) NOT NULL,
  `youtube_id` varchar(32) DEFAULT NULL,
  `refs` text NOT NULL,
  `platforms` varchar(6) NOT NULL,
  PRIMARY KEY (`article_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1;       

CREATE TABLE IF NOT EXISTS `article_categories` (
  `category_id` int(15) NOT NULL AUTO_INCREMENT,
  `parent_id` int(15) NOT NULL,
  `title` varchar(50) NOT NULL,
  `description` text NOT NULL,
  `attachment_id` text NOT NULL,
  `enable_comments` tinyint(1) NOT NULL,
  `enable_ratings` tinyint(1) NOT NULL,
  `guest_reading` tinyint(1) NOT NULL,
  `platform_assoc` tinyint(1) NOT NULL,
  `allowed_types` varchar(6) NOT NULL,
  PRIMARY KEY (`category_id`,`title`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1;

这是我到目前为止提出的查询:

            SELECT
                c.category_id, c.title, c.description,
                a.article_id, a.category_id, a.title, COUNT(a.article_id) AS total_articles
            FROM article_categories AS c
            LEFT JOIN articles AS l ON (
                SELECT
                    article_id AS article_id, category_id, title AS article_title
                FROM articles AS l
                WHERE l.category_id = c.category_id
                ORDER BY l.article_id
                DESC LIMIT 1)
            LEFT JOIN articles AS a ON (c.category_id = a.category_id)
            GROUP BY c.category_id
            ORDER BY c.title ASC

上面的查询给了我以下 SQL 错误:

Operand should contain 1 column(s)

为什么会这样?

【问题讨论】:

    标签: mysql join fetch


    【解决方案1】:

    您可以使用一个查询返回所有类别的列表和每个类别中的最近文章,试试这个

    SELECT C.*, A.*
    FROM article_categories C
    LEFT OUTER JOIN articles A ON c.category_id = A.category_id
    WHERE 
    (
     A.category_id IS NULL OR 
     A.article_id = (SELECT MAX(X.article_id)
                     FROM articles X WHERE X.category_id = C.category_id)
    )
    

    【讨论】:

    • 我还需要该类别的最后一篇文章的标题。我该怎么做?如果我在子查询中的 select 语句中添加另一个字段,我会得到原来的错误。
    【解决方案2】:

    这会将文章限制为每个类别的最高 article_id 并利用这些表上的索引:

    select
          ac.category_id, ac.title, newa.article_id, newa.title article_title
    from article_categories ac
    left join articles newa on ac.category_id = newa.category_id
    left join articles olda on newa.category_id = olda.category_id
                        and olda.article_id > newa.article_id
    where olda.article_id is null
    ;
    

    See this Demonstrated at SQLFiddle

    【讨论】:

      【解决方案3】:

      鞋带,我正在浏览你的其他问题,发现这个问题没有解决,所以我决定尝试一下。

      这有点棘手,但假设我正确理解您的问题,我认为这并不算太糟糕。首先,获取每个类别的最新文章日期:

      SELECT a.category_id, MAX(a.date_posted)
      FROM articles a
      JOIN article_categories c ON c.category_id = a.category_id
      GROUP BY a.category_id;
      

      然后,在 category_id 和 date 相等且您拥有所需内容的条件下,将其与您的文章表连接:

      SELECT ar.*
      FROM articles ar
      JOIN(SELECT a.category_id, MAX(a.date_posted) AS latestDateForCategory
          FROM articles a
          JOIN article_categories c ON c.category_id = a.category_id
          GROUP BY a.category_id) t
      ON t.category_id = ar.category_id AND t.latestDateForCategory = ar.date_posted;
      

      SQL Fiddle.

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-11-22
        • 1970-01-01
        • 2016-05-15
        • 1970-01-01
        • 1970-01-01
        • 2019-07-25
        • 1970-01-01
        相关资源
        最近更新 更多