0

假设你有

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

问候

4

2 回答 2

0

下一篇博客文章描述了您的查询的解决方案: SQL: selection top N records per group

它需要一个额外的小数字表,用于通过字符串遍历技术“迭代”每组的前 N ​​个值。它使用 GROUP_CONCAT 来克服 MySQL 不支持窗口函数的事实。这也意味着它不是一个漂亮的景象!

这种技术的一个优点是它不需要子查询,并且可以最佳地利用表上的索引。

要完成对您问题的回答,我们必须添加一个额外的列:您已请求每组每个项目的计数器。

这是一个使用世界样本数据库的示例,选择每个大陆的前 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
;
于 2012-07-06T17:21:57.680 回答
0

我假设 和 的组合idvalue独一无二的。以下是不使用 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
于 2012-07-04T03:19:47.987 回答