【问题标题】:Select all second highest values only from temp table仅从临时表中选择所有第二高的值
【发布时间】:2015-08-04 08:43:56
【问题描述】:

使用 T-SQL (SQL Server 2008 R2),我试图仅列出临时表中特定列中具有第二高值的行,然后将结果放入新的临时表中。 PK 是ID,它可以有不断增加的版本号,然后是唯一代码。

例子:

 ID | Name| Version | Code
------------------------
 1  | A   | 1       | 10
 1  | A   | 2       | 20
 1  | A   | 3       | NULL
 2  | B   | 1       | 40
 2  | B   | 2       | 50
 2  | C   | 1       | 60

查询的期望结果是

ID |  Version | Code
------------------------
1  |  2       | 20
2  |  1       | 40

为了实现这一点,只要结果给出的版本号大于 1,我需要调整以下查询以提取第二高的值。这些结果来自临时表,然后将被放入最终结果临时桌子。 编辑:请注意,这将应用于超过 33000 行数据,所以我更喜欢比 INSERT VALUES 更简洁的东西。谢谢。

当前查询:

SELECT
    ID
    ,Version
    ,Code
INTO 
    #table2
FROM
    #table1

SELECT * 
FROM #table2
WHERE Version > 1
ORDER BY ID asc

DROP TABLE #table1
DROP TABLE #table2

我尝试运行 where 子句 WHERE Version < (SELECT MAX(VERSION) FROM #TABLE 2) 但这没有效果,可能是由于唯一的代码值,并且在任何情况下都无法在我有超过 3 个版本的情况下工作。

我们将不胜感激。

提前致谢。

【问题讨论】:

    标签: sql-server tsql sql-server-2008-r2


    【解决方案1】:

    我已经测试了下面的代码,它给出的输出是你想要的查询结果是

    SELECT ID,Name,[Version],Code
    FROM (
            SELECT ROW_NUMBER() OVER (PARTITION BY NAME ORDER BY [Version] DESC) AS RNK,*
            FROM
                (
                    SELECT 1 ID, 'A' Name ,1 [Version] ,10 Code
                    UNION ALL
                    SELECT 1, 'A', 2 ,20
                    UNION ALL
                    SELECT 1, 'A', 3 ,30
                    UNION ALL
                    SELECT 1, 'A', 4 ,NULL
                    UNION ALL
                    SELECT 2, 'B', 1 ,40
                    UNION ALL
                    SELECT 2, 'B', 2 ,50
                    UNION ALL
                    SELECT 2, 'C', 1 ,60
                )B
            )BASE
    WHERE RNK =2
    

    【讨论】:

    • 感谢您的解决方案,但不幸的是,由于我在现实中处理的数据量很大(33000 行),这并不实用。我已经更新了问题。
    • 根据你的表你可以试试这个:SELECT ID,Name,[Version],Code FROM ( SELECT ID,Name,[Version],Code,ROW_NUMBER() OVER (PARTITION BY NAME ORDER BY [版本] DESC) AS RNK FROM [你的表名])base WHERE RNK = 2
    • 现货 - 这是我已经适应了我想要的结果的解决方案(改为按版本分区)。非常感谢。
    【解决方案2】:

    如果您的主键只有 ID,则您有重复的行。所以我假设你的主键是别的东西,例如 ID、版本、名称。您有两行具有相同 ID 和相同版本,您想对此应用什么样的规则?最低数?

    我做了一个你想要的例子:

    首先声明必要的表:

    declare @table1 table (
        Id int,
        Name nvarchar(20),
        [Version] int,
        Code int
    )
    
    insert into @table1 values (1,'A',1,10),(1,'A',2,20),(1,'A',3,30),(1,'A',4,NULL)
                              ,(2,'B',1,40),(2,'B',2,50),(2,'C',1,60);
    

    然后查询得到结果:

    with HighestVersions (Id, MaxVersion) As 
    (
        select Id, max(version) from @table1 group by Id
    )
    select
        t1.Id,
        t1.[Version],
        min(t1.Code) as Code
    from
        @table1 t1
        inner join
            HighestVersions hv
            on
                hv.Id = t1.Id
                and (hv.MaxVersion-1) = t1.[Version]
    group by
        t1.Id
        ,t1.[Version]
    

    我不得不对最外层的选择做了一个小技巧,这是因为重复的“Id”和“Version”。否则你会得到两行 ID = 2, Version = 1

    如果您想删除 NULL 值,您可以更改 WITH 部分(根据您上次的编辑):

    with HighestVersions (Id, MaxVersion) As 
    (
        select Id, max(version) from @table1 where Code is not null group by Id
    )
    

    【讨论】:

    • 感谢您的建议,Joeri - 关于 PK,您是对的……ID 是另一个表的唯一 PK,我最终会将这些结果加入到该表中,所以这可能是混乱。尽管如此,这将是我上面要求的结果 table2 表的 PK。您的解决方案不太适合我,因为我实际上正在处理 33k+ 行数据,所以我需要一些比插入所有这些值更简洁的东西!
    【解决方案3】:

    试试这个:

    DECLARE @List TABLE (ID int, Name char(1), Version int, Code int NULL)
    
    INSERT INTO @List
    VALUES
    (1, 'A', 1, 10),
    (1, 'A', 2, 20),
    (1, 'A', 3, 30),
    (1, 'A', 4, NULL),
    (2, 'B', 1, 40),
    (2, 'B', 2, 50),
    (2, 'C', 1, 60)
    
    
    SELECT
        ID, Name, Version, Code
    FROM
       (
        SELECT
            *,
           ROW_NUMBER() OVER (PARTITION BY ID, Name ORDER BY Version DESC) Rn
        FROM @List
       ) a
    WHERE
        a.Rn = 2
    

    【讨论】:

    • 感谢您的解决方案,但不幸的是,由于我在现实中处理的数据量很大(33000 行),这并不实用。我已经更新了问题。
    猜你喜欢
    • 2023-03-24
    • 2013-09-15
    • 2019-10-19
    • 2010-12-21
    • 2013-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多