代码之家  ›  专栏  ›  技术社区  ›  DDan

SQL Server查询项中包含查询中但保持顺序的项

  •  0
  • DDan  · 技术社区  · 6 年前

    | ID   | RES  |
    ---------------
    | A_12 | 1.89 |
    | B_27 | 4.53 |
    | B_28 | 1.02 |
    | C_23 | 2.67 |
    

    工具生成的特定顺序不遵循任何标准排序规则,我无法更改该顺序。 我想做一个简单的查询,通过一个列表id收集所有需要的记录,并给我一个自定义的有序结果列表。

    比如:

    SELECT RES FROM TABLE1 WHERE ID IN ('A_12', 'C_23', 'B_28', 'B_27')
    

    我希望它能回来

    1.89 
    2.67
    1.02
    4.53
    

    我理解 IN 查询不会遵循顺序,因为它很可能被翻译成 (ID = A OR ID = B OR ID = C) 查询。

    如何强制IN查询的结果以维护定义的顺序?我是否需要创建一个只有一列的临时表来维护顺序?有什么好办法吗?

    5 回复  |  直到 6 年前
        1
  •  2
  •   Denis Rubashkin    6 年前

    JOIN 而不是使用 IN

    DECLARE @Test TABLE (
        ID  VARCHAR(32),
        RES DECIMAL(5,2)
    )
    
    INSERT @Test (ID, RES)
    VALUES
    ('A_12', 1.89),
    ('B_27', 4.53),
    ('B_28', 3.54),
    ('C_23', 2.67)
    
    
    SELECT t.ID, t.RES
    FROM @Test t
        JOIN (
            VALUES
            ('A_12', 1),
            ('C_23', 2),
            ('B_28', 3),
            ('B_27', 4)
        ) o(ID, OrderId) ON t.ID = o.ID
    ORDER BY o.OrderId
    
        2
  •  2
  •   sepupic    6 年前

    您可以使用 values

    declare @table1 table(id varchar(10), res decimal(10,2));
    insert into @table1 (id, res)
    values 
    ('A_12', 1.89),
    ('B_27', 4.53),
    ('B_28', 3.54),
    ('C_23', 2.67);
    
    select t.*
    from @table1 t
         join (values(1, 'A_12'), (2, 'C_23'), (3, 'B_28'), (4, 'B_27')) v(id,val)
            on t.id = v.val
    order by v.id;
    

    @Table1 这是你身体的替代品 Table1 .

        3
  •  1
  •   TomTom    6 年前

    所以,没有秩序可循。句号。

    如果您想保留一个,请为in中的valeus使用一个临时表/表变量(显然是一个联接),并按在该变量的第二个字段中也保持的顺序排序。

        4
  •  0
  •   DDan    6 年前

    我是否需要创建一个只有一列的临时表来维护顺序

    create table #tmp
    (
      CustomOrder int,
      ID varchar(100)
    )
    
    insert into #tmp values (1, 'A_12')
    insert into #tmp values (2, 'C_23')
    insert into #tmp values (3, 'B_28')
    insert into #tmp values (4, 'B_27')
    

    查询:

    SELECT RES FROM TABLE1 INNER JOIN #tmp ON TABLE1.ID = #tmp.ID WHERE TABLE1.ID IN ('A_12', 'C_23', 'B_28', 'B_27')
    ORDER BY #tmp.CustomOrder
    

    1.89 
    2.67
    1.02
    4.53
    

        5
  •  0
  •   SNR    6 年前

    只是另一种方法:

    SELECT RES FROM TABLE1 WHERE ID IN ('A_12')
    UNION ALL
    SELECT RES FROM TABLE1 WHERE ID IN ('C_23')
    UNION ALL
    SELECT RES FROM TABLE1 WHERE ID IN ('B_28')
    UNION ALL
    SELECT RES FROM TABLE1 WHERE ID IN ('B_27')
    

    我以为 JOIN 选择比这种方法更有效。如果要自动执行此选项:

    DROP TABLE #TABLE1
    
    CREATE TABLE #TABLE1(ID NVARCHAR(4), RES FLOAT)
    
    INSERT INTO #TABLE1 VALUES('A_12',1.89)
    INSERT INTO #TABLE1 VALUES('B_27',4.53)
    INSERT INTO #TABLE1 VALUES('B_28',1.02)
    INSERT INTO #TABLE1 VALUES('C_23',2.67)
    
    DECLARE @ID TABLE(ID NVARCHAR(4) not null);
    
    --HERE HAVE TO INSERT IN ORDER YOU WANT TO RETURN THE RESULTS IN THE QUERY
    insert into @ID VALUES('A_12')
    insert into @ID VALUES('B_27')
    insert into @ID VALUES('B_28')
    insert into @ID VALUES('C_23')
    
    DECLARE @UNIONALL  NVARCHAR(10)  = CHAR(13) + N'UNION ALL' 
    DECLARE @QUERY     NVARCHAR(MAX) = NULL
    DECLARE @ID_SEARCH NVARCHAR(4)   = NULL
    
    DECLARE C CURSOR FAST_FORWARD FOR SELECT ID FROM @ID
    OPEN C 
    
    FETCH NEXT FROM C INTO @ID_SEARCH
    
    SET @QUERY = N'SELECT RES FROM #TABLE1 WHERE ID = ''' + @ID_SEARCH + ''' '
    
    FETCH NEXT FROM C INTO @ID_SEARCH
    
    WHILE @@FETCH_STATUS = 0 BEGIN
        SET @QUERY = @QUERY + @UNIONALL
        SET @QUERY = @QUERY +  N' SELECT RES FROM #TABLE1 WHERE ID = ''' + @ID_SEARCH + ''' '
    
        FETCH NEXT FROM C INTO @ID_SEARCH 
    END
    
    EXECUTE master..sp_executesql @QUERY