【问题标题】:For each Id2 value, get a row with the lowest Id1, and another row with the highest Id1对于每个 Id2 值,获取 Id1 最低的一行,以及 Id1 最高的另一行
【发布时间】:2020-11-19 18:24:29
【问题描述】:

我有一个有 2 列的表格,如下所示:

Id1     Id2
------------
5286    1481
5391    1482
5546    1483
5702    1482
5747    1482
5833    1484
5850    1482
5878    1485
6000    1482
6035    1486
6181    1482
6259    1481
6274    1487
6378    1488
6379    1489
6400    1482
6469    1485
6575    1485
6822    1488
6876    1481
6901    1482
6931    1481
6939    1490
7083    1491
7214    1482
7241    1492
7429    1493
7498    1482
7541    1482
7618    1494
7745    1495
7797    1496
7869    1482

对于每个Id2 值,我想获得Id1 最低的一行,以及Id1 最高的另一行,例如Id2 = 1482

1482    5391
1482    7869

如何编写我的 (Transact) SQL 查询来实现这一点?

提前谢谢你。

【问题讨论】:

  • 嗨,Bruno,您是否阅读了有关如何在 StackOverflow 上提出好问题的指南?在stackoverflow.com/help/how-to-ask 上查看它们。通常,您应该自己尝试解决问题,并提供您尝试了哪些步骤作为问题的一部分,以便我们能够提供建设性的答案,而不仅仅是简单的代码。
  • 您好,我没有尝试任何查询来实现这一点,因为我不知道如何做到这一点:在一个选择语句中,在多个选择语句中,使用中间表...... ?

标签: sql sql-server tsql


【解决方案1】:

试试这样:http://sqlfiddle.com/#!18/db733/3/0

SELECT [Id2], MIN(Id1) AS [Id1]
FROM [table]
GROUP BY [Id2]

UNION ALL

SELECT [Id2], MAX(Id1) AS [Id1]
FROM [table]
GROUP BY [Id2]

ORDER BY [Id2], [Id1]

通过使用分组,您可以找到[Id2] 的每个值对应的maxmin

【讨论】:

  • 谢谢,它成功了!我刚刚用 UNION 替换了 UNION ALL 以避免重复,以防 min(Id1)=max)id1)
  • 不错!是的,如果不需要重复,这也是可能的。
【解决方案2】:

你可以试试这样的:

WITH CTE AS
(
    SELECT
        ID1, ID2, 
        RnFirst = ROW_NUMBER() OVER (PARTITION BY ID2 ORDER BY ID1),
        RnLast = ROW_NUMBER() OVER (PARTITION BY ID2 ORDER BY ID1 DESC)
    FROM    
        dbo.YourTableNameHere
)
SELECT 
    ID1, ID2,
    CASE
        WHEN RnFirst = 1 THEN 'Highest'
        WHEN RnLast = 1 THEN 'Lowest'
    END AS Label
FROM 
    CTE
WHERE 
    ID2 = 1482 
    AND (RnFirst = 1 OR CTE.RnLast = 1)

CTE(公用表表达式)通过 ID2 创建“分区”(存储桶)并对内部的值进行编号 - 一次通过升序 ID1 值,一次通过降序值。

因此,最高值和最低值都标记为 row.no 1 - 升序一次,降序一次。

【讨论】:

    【解决方案3】:

    你可以得到MINMAX和“unpivot”:

    WITH CTE AS(
        SELECT MIN(ID1) AS MinID1,
               MAX(ID1) AS MaxID1,
               ID2
        FROM dbo.YourTable
        GROUP BY ID2)
    SELECT V.ID1,
           C.ID2
    FROM CTE C
         CROSS APPLY (VALUES('Min',C.MinID1),
                            ('Max',C.MaxID1))V(KPI,ID1);
               
    

    【讨论】:

      【解决方案4】:
      WITH CTE AS
      (
        SELECT MIN(Id1) AS MINID1 , MAX(Id1) AS MAXID1 FROM IDSS
      )
      SELECT D1.Id2 , CTE.MINID1 AS [VALUE] FROM IDSS D1
      CROSS JOIN CTE
      UNION ALL
      SELECT D1.Id2 , CTE.MAXID1 AS [VALUE]  FROM IDSS D1
      CROSS JOIN CTE
      ORDER BY D1.Id2, [VALUE]
      

      用于测试的脚本:

      CREATE TABLE IDSS (Id1 INT,     Id2 INT)
      
      INSERT INTO IDSS VALUES
      (5286 ,   1481),
      (5391  ,  1482),
      (5546 ,   1483)
      
      WITH CTE AS
      (
        SELECT MIN(Id1) AS MINID1 , MAX(Id1) AS MAXID1 FROM IDSS
      )
      SELECT D1.Id2 , CTE.MINID1 AS [VALUE] FROM IDSS D1
      CROSS JOIN CTE
      UNION ALL
      SELECT D1.Id2 , CTE.MAXID1 AS [VALUE]  FROM IDSS D1
      CROSS JOIN CTE
      ORDER BY D1.Id2, [VALUE]
      

      结果:

      +------+-------+
      | Id2  | VALUE |
      +------+-------+
      | 1481 | 5286  |
      +------+-------+
      | 1481 | 5546  |
      +------+-------+
      | 1482 | 5286  |
      +------+-------+
      | 1482 | 5546  |
      +------+-------+
      | 1483 | 5286  |
      +------+-------+
      | 1483 | 5546  |
      +------+-------+
      

      【讨论】:

      • LEFT JOIN CTE ON 1=1? 1 什么时候不等于 1?
      猜你喜欢
      • 2015-07-12
      • 2019-06-19
      • 2020-06-15
      • 2011-08-13
      • 1970-01-01
      • 2016-04-25
      • 1970-01-01
      • 2019-06-09
      相关资源
      最近更新 更多