Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/73.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何选择每组的顶部和底部记录?_Sql_Sql Server 2008 - Fatal编程技术网

Sql 如何选择每组的顶部和底部记录?

Sql 如何选择每组的顶部和底部记录?,sql,sql-server-2008,Sql,Sql Server 2008,比如说,我在数据库(SQLServer2008)中有一个表,其中的数据与此类似 (但要大得多): 我想获得每个组的顶部和底部记录的ID,其中每个组的记录按分数排序(补充,ID),如下所示: | GROUP | MIN_ID | MAX_ID | ---------------------------- | A | 10 | 3 | | B | 8 | 8 | | C | 4 | 7 | | D |

比如说,我在数据库(SQLServer2008)中有一个表,其中的数据与此类似 (但要大得多):

我想获得每个
组的顶部和底部记录的
ID
,其中每个组的记录按
分数排序(补充,
ID
),如下所示:

| GROUP | MIN_ID | MAX_ID  |
----------------------------
| A     | 10     | 3       |
| B     | 8      | 8       |
| C     | 4      | 7       |
| D     | 1      | 5       |
问题是:我如何才能做到这一点

到目前为止,我一直在尝试基于
RANK()
函数的解决方案,但还没有找到一个既能生成正确的输出,又效率不高或可维护的查询


注:

这个例子被简化了。我的“表”实际上是一个已经很复杂的查询的输出,我希望将最后的阶段添加到其中。我宁愿只从表中选择一次

如果可能,最好有一个通用解决方案,允许我选择每组的顶部和底部
n

ID
s的顺序不方便

DECLARE @YourTable TABLE (ID INTEGER, Score INTEGER, [Group] VARCHAR(1))
INSERT INTO @YourTable VALUES (10, 1, 'A')
INSERT INTO @YourTable VALUES (6 , 2, 'A')
INSERT INTO @YourTable VALUES (3 , 3, 'A')
INSERT INTO @YourTable VALUES (8 , 5, 'B')
INSERT INTO @YourTable VALUES (4 , 1, 'C')
INSERT INTO @YourTable VALUES (9 , 3, 'C')
INSERT INTO @YourTable VALUES (2 , 4, 'C')
INSERT INTO @YourTable VALUES (7 , 4, 'C')
INSERT INTO @YourTable VALUES (12, 3, 'D')
INSERT INTO @YourTable VALUES (1 , 3, 'D')
INSERT INTO @YourTable VALUES (11, 4, 'D')
INSERT INTO @YourTable VALUES (5 , 6, 'D')  



任何解决方案都需要一些关于组和分数的良好索引,但包括ID

SELECT
    foo.[Group],
    m1.ID AS Min_ID,
    m2.ID AS Max_ID
FROM
    (
    SELECT
       [Group], MIN(Score) AS MinScore, MAX(Score) AS MaxScore
    FROM
       mytable
    GROUP BY
       [Group]
    ) foo
    JOIN
    mytable m1 ON foo.[Group] = m1.[Group] AND foo.MinScore = m1.Score
    JOIN
    mytable m2 ON foo.[Group] = m2.[Group] AND foo.MaxScore = m2.Score
然而,在您的示例数据中,这也起作用,因为ID和分数是按顺序对齐的:

SELECT
    [Group],
    MIN(ID) AS Min_ID,
    MAX(ID) AS Max_ID
FROM
    mytable
GROUP BY
    [Group]

任何解决方案都需要一些关于组和分数的良好索引,但包括ID

SELECT
    foo.[Group],
    m1.ID AS Min_ID,
    m2.ID AS Max_ID
FROM
    (
    SELECT
       [Group], MIN(Score) AS MinScore, MAX(Score) AS MaxScore
    FROM
       mytable
    GROUP BY
       [Group]
    ) foo
    JOIN
    mytable m1 ON foo.[Group] = m1.[Group] AND foo.MinScore = m1.Score
    JOIN
    mytable m2 ON foo.[Group] = m2.[Group] AND foo.MaxScore = m2.Score
然而,在您的示例数据中,这也起作用,因为ID和分数是按顺序对齐的:

SELECT
    [Group],
    MIN(ID) AS Min_ID,
    MAX(ID) AS Max_ID
FROM
    mytable
GROUP BY
    [Group]
如果可能,最好有一个通用解决方案,允许我选择每组的顶部和底部
n

如果可能,最好有一个通用解决方案,允许我选择每组的顶部和底部
n


您可以使用子查询(
选择TOP 1
)…

您可以使用子查询(
选择TOP 1
)…

您希望分数也一样,还是只希望输出按分数排序?TOP 1还是TOP n?差别很大…@j_random_hacker:我不在乎分数。@gbn:是的,我知道。“我会很高兴拿到前1名的。”阿杰·莱恩:如果你不在乎分数,你最好把它们从图片中删掉。看看答案,你的问题会有不同的解释。你是希望分数也一样,还是只希望输出按分数排序?前1名还是前n名?差别很大…@j_random_hacker:我不在乎分数。@gbn:是的,我知道。“我会很高兴拿到前1名的。”阿杰·莱恩:如果你不在乎分数,你最好把它们从图片中删掉。看看答案,你的问题会有不同的解释。在阅读了你的解决方案后,我想我终于明白OP想要什么了。根据他在示例中给出的值,我的解决方案给出的结果与您的解决方案相同。谢谢。是的,他补充了一条评论来澄清。我想我有TDD。。。创造可能有效的最简单的东西。在阅读了你的解决方案后,我想我终于明白OP想要什么了。根据他在示例中给出的值,我的解决方案给出的结果与您的解决方案相同。谢谢。是的,他补充了一条评论来澄清。我想我有TDD。。。创造可能有效的最简单的东西。
WITH q AS
        (
        SELECT  m.*,
                ROW_NUMBER() OVER (PARTITION BY Group ORDER BY Score) AS rn_asc,
                ROW_NUMBER() OVER (PARTITION BY Group ORDER BY Score DESC) AS rn_desc
        FROM    mytable m
        )
SELECT  *
FROM    q
WHERE   rn_asc BETWEEN 1 AND 10
        OR rn_desc BETWEEN 1 AND 10