如何在没有分组的情况下聚合数据

时间:2013-08-21 20:44:17

标签: mysql group-by aggregation

我在这里遇到一些情况。

环境

我这里有一个系列数据库。 系列本身有一张桌子,一张用于连接到系列表的季节,一张用于连接到四季表的剧集。 由于不同国家/地区有空气日期,因此我有另一张名为'series_data`的表格,如下所示:

CREATE TABLE IF NOT EXISTS `episode_data` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `episode_id` int(11) NOT NULL,
  `country` char(3) NOT NULL,
  `title` varchar(255) NOT NULL,
  `date` date NOT NULL,
  `tba` tinyint(1) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `episode_id` (`episode_id`),
  KEY `date` (`date`),
  KEY `country` (`country`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

现在我正尝试使用以下查询从数据库中的每个系列收集最后播出的剧集:

SELECT
    *
FROM
    `episode_data` ed
WHERE
    `ed`.`date` < CURDATE( ) &&
    `ed`.`date` != '1970-01-01' &&
    `ed`.`series_id` = 1
GROUP BY
    `ed`.`country` DESC
ORDER BY
    `ed`.`date` DESC 

由于我已将所有内容规范化,因此我将'episode_id'更改为'series_id',以使查询更简单。

我想要完成的事情

我希望每个国家的最后播出的剧集实际上已宣布(eddate!='1970-01-01')作为一个查询的返回结果。

问题是什么

我现在知道了(搜索谷歌,发现不是我在这里工作的答案),订购发生在分组之后,所以我的“约会”排序完全没用。

另一个问题是上面的查询是有效的,但是总是将那些id最低的条目与我的条件匹配,因为那些是表索引中的第一个。

问题是什么?

如何实现上述目标。我不知道分组是否是正确的方法。如果没有“一个班轮”,我认为唯一的方法是我想避免的子查询,因为据我所知,这比设置正确索引的一个班轮慢。

希望这里有你需要的一切:)

示例数据

CREATE TABLE IF NOT EXISTS `episode_data` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `episode_id` int(11) NOT NULL,
  `country` char(3) NOT NULL,
  `title` varchar(255) NOT NULL,
  `date` date NOT NULL,
  `tba` tinyint(1) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `episode_id` (`episode_id`),
  KEY `date` (`date`),
  KEY `country` (`country`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

INSERT INTO `episode_data` (`id`, `episode_id`, `country`, `title`, `date`, `tba`) VALUES
(4942, 2471, 'de', 'Väter und Töchter', '2013-08-06', 0),
(4944, 2472, 'de', 'Neue Perspektiven', '2013-08-13', 0),
(5013, 2507, 'us', 'Into the Deep', '2013-08-06', 0),
(5015, 2508, 'us', 'The Mirror Has Three Faces', '2013-08-13', 0);

注意! 这是具有“EPISODE_ID”而不是“SERIES_ID”的原始表数据。

我想要的数据是那些与今天最接近的数据,这里是4944和5015。

1 个答案:

答案 0 :(得分:0)

如果您想要每个国家/地区的最后播出日期,请使用此聚合:

SELECT country, max(date) as lastdate
FROM `episode_data` ed
WHERE `ed`.`date` < CURDATE( ) AND
      `ed`.`date` != '1970-01-01' AND
      `ed`.`series_id` = 1
GROUP BY `ed`.`country`;

如果您也尝试获取episode_idtitle,可以使用group_concat()substring_index()

SELECT country, max(date) as lastdate,
       substring_index(group_concat(episode_id order by date desc), ',', 1
                      ) as episode_id,
       substring_index(group_concat(title order by date desc separator '|'), '|', 1
                      ) as title
FROM `episode_data` ed
WHERE `ed`.`date` < CURDATE( ) AND
      `ed`.`date` != '1970-01-01' AND
      `ed`.`series_id` = 1
GROUP BY `ed`.`country`;

请注意,这会为标题使用不同的分隔符,前提是它可能有逗号。