假设你有
id / value
1 2
1 3
1 6
2 3
3 1
3 3
3 6
我想要检索每个id组至少n行,假设n = 4.此外,如果将计数器添加为列,将会有所帮助。所以结果应该是:
counter / id / value
1 1 2
2 1 3
3 1 6
4 null null
1 2 3
2 null null
3 null null
4 null null
1 3 1
2 3 3
3 3 6
4 null null
问候
答案 0 :(得分:0)
我假设id
和value
的组合是唯一的。以下是不使用MySQL变量的方法:
SELECT
a.n AS counter,
b.id,
b.value
FROM
(
SELECT
aa.n,
bb.id
FROM
(
SELECT 1 AS n UNION ALL
SELECT 2 AS n UNION ALL
SELECT 3 AS n UNION ALL
SELECT 4 AS n
) aa
CROSS JOIN
(
SELECT DISTINCT id
FROM tbl
) bb
) a
LEFT JOIN
(
SELECT aa.id, aa.value, COUNT(*) AS rank
FROM tbl aa
LEFT JOIN tbl bb ON aa.id = bb.id AND aa.value >= bb.value
GROUP BY aa.id, aa.value
) b ON a.id = b.id AND a.n = b.rank
ORDER BY
a.id,
a.n
答案 1 :(得分:0)
下一篇博客文章介绍了查询的解决方案: SQL: selecting top N records per group
它需要一个额外的小数字表,用于通过String Walking技术“迭代”每组的前N个值。 它使用GROUP_CONCAT作为克服MySQL不支持窗口函数的一种方法。这也意味着它不是一个美丽的景象!
这种技术的一个优点是它不需要子查询,并且可以最佳地利用表上的索引。
要完成问题的答案,我们必须添加其他列:您已为每个组的每个项目请求了一个计数器。
以下是使用 world 示例数据库的示例,选择每个大洲最大的5个县:
CREATE TABLE `tinyint_asc` (
`value` tinyint(3) unsigned NOT NULL default '0',
PRIMARY KEY (value)
) ;
INSERT INTO `tinyint_asc` VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),(13),(14),(15),(16),(17),(18),(19),(20),(21),(22),(23),(24),(25),(26),(27),(28),(29),(30),(31),(32),(33),(34),(35),(36),(37),(38),(39),(40),(41),(42),(43),(44),(45),(46),(47),(48),(49),(50),(51),(52),(53),(54),(55),(56),(57),(58),(59),(60),(61),(62),(63),(64),(65),(66),(67),(68),(69),(70),(71),(72),(73),(74),(75),(76),(77),(78),(79),(80),(81),(82),(83),(84),(85),(86),(87),(88),(89),(90),(91),(92),(93),(94),(95),(96),(97),(98),(99),(100),(101),(102),(103),(104),(105),(106),(107),(108),(109),(110),(111),(112),(113),(114),(115),(116),(117),(118),(119),(120),(121),(122),(123),(124),(125),(126),(127),(128),(129),(130),(131),(132),(133),(134),(135),(136),(137),(138),(139),(140),(141),(142),(143),(144),(145),(146),(147),(148),(149),(150),(151),(152),(153),(154),(155),(156),(157),(158),(159),(160),(161),(162),(163),(164),(165),(166),(167),(168),(169),(170),(171),(172),(173),(174),(175),(176),(177),(178),(179),(180),(181),(182),(183),(184),(185),(186),(187),(188),(189),(190),(191),(192),(193),(194),(195),(196),(197),(198),(199),(200),(201),(202),(203),(204),(205),(206),(207),(208),(209),(210),(211),(212),(213),(214),(215),(216),(217),(218),(219),(220),(221),(222),(223),(224),(225),(226),(227),(228),(229),(230),(231),(232),(233),(234),(235),(236),(237),(238),(239),(240),(241),(242),(243),(244),(245),(246),(247),(248),(249),(250),(251),(252),(253),(254),(255);
SELECT
Continent,
SUBSTRING_INDEX(
SUBSTRING_INDEX(
GROUP_CONCAT(Name ORDER BY SurfaceArea DESC),
',', value),
',', -1)
AS Name,
CAST(
SUBSTRING_INDEX(
SUBSTRING_INDEX(
GROUP_CONCAT(SurfaceArea ORDER BY SurfaceArea DESC),
',', value),
',', -1)
AS DECIMAL(20,2)
) AS SurfaceArea,
CAST(
SUBSTRING_INDEX(
SUBSTRING_INDEX(
GROUP_CONCAT(Population ORDER BY SurfaceArea DESC),
',', value),
',', -1)
AS UNSIGNED
) AS Population,
tinyint_asc.value AS counter
FROM
Country, tinyint_asc
WHERE
tinyint_asc.value >= 1 AND tinyint_asc.value <= 5
GROUP BY
Continent, value
;