【问题标题】:order selected columns by ascending order按升序排列选定的列
【发布时间】:2015-12-31 09:40:44
【问题描述】:

我有一张这样的桌子;

Reg_No      Student_Name         col1    col2    col3
----------- -------------------- ------ ------ ------
101         Kevin                77          94          78
102         Andrew               91          81          17
103         Scott                46          83          28

我如何能够选择 col1、col2、col3 并将从 col1、col2、col3 中选择的值从每一行按升序排列,但保持访问表的顺序,使其如下所示?

Reg_No      Student_Name         Lowest    Middle    Highest
----------- ------------------- --------- --------- ---------
101         Kevin                77          78          94
102         Andrew               17          81          91
103         Scott                28          46          83

我正在使用 MSSQL Server 2008 R2

【问题讨论】:

  • 关系型数据库不能这样工作,虽然可以在 sql 中实现,但我建议你在存储期间或最终输出期间这样做
  • 排序是一个列操作。我认为没有一种简单的方法可以满足您的要求

标签: sql-server sql-server-2008


【解决方案1】:

这在 SQL Server 中有点痛苦。一种方法是取消透视数据,然后重新透视。我倾向于使用条件聚合来做到这一点:

select Reg_No, Student_Name,
       max(case when seqnum = 1 then col end) as Lowest,
       max(case when seqnum = 2 then col end) as Middle,
       max(case when seqnum = 3 then col end) as Highest
from (select t.*, v.col,
             row_number() over (partition by Reg_No, Student_Name order by v.col) as seqnum
      from likethis t cross apply
           (values (t.col1), (t.col2), (t.col3)
           ) v(col)
     ) t
group by Reg_No, Student_Name;

如果您尝试使用 case 语句执行此操作,它们将变得相当复杂,因为可能存在关联和 NULL 值。

【讨论】:

    【解决方案2】:

    您确实需要标准化您的数据,但在那之前:

    with temp (ColNo, Reg_No, Student_Name, col) as
       select 1, Reg_No, Student_Name, col1
       from Students
       union all
       select 2, Reg_No, Student_Name, col2
       from Students
       union all
       select 3, Reg_No, Student_Name, col3
       from Students;
    
    
    select 
       min(t1.col) as Lowest,
       max(t2.col) as Middle
       max(t1.col) as Highest
    from temp t1
    join t2
    on t1.Reg_No = t2.Reg_No
       and t1.Student_Name = t1.Student_Name
       and t1.ColNo <> t2.ColNo  -- don't match on self
       and t1.col >= t2.col      -- don't include the max in t2 unless more than 1
    group by t1.Reg_No, t1.Student_Name
    order by t1.Reg_No, t1.Student_Name
    

    所以如果 (col1, col2, col3) 的集合是 (1, 2, 3) 那么 t2 最终是 (1, 2),其中最大值是 2。

    如果集合为 (3, 3, 1),则 t2 最终为 (3, 3, 1),其中最大值为 3。

    【讨论】:

      【解决方案3】:

      这是一种不生成Row_Number的方法

      WITH cte 
           AS (SELECT reg_no, 
                      student_name, 
                      Max(v.col)OVER(partition BY reg_no, student_name) AS highest, 
                      Min(v.col)OVER(partition BY reg_no, student_name) AS lowest, 
                      col 
               FROM   Yourtable t 
                      CROSS apply (VALUES (t.col1),(t.col2),(t.col3) ) v(col)) 
      SELECT reg_no, 
             student_name, 
             lowest=Min(lowest), 
             Middle=Min(CASE WHEN col <> lowest AND col <> highest THEN col END), 
             highest=Max(highest) 
      FROM   cte 
      GROUP  BY reg_no, 
                student_name 
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-04-11
        • 2018-08-11
        • 2013-10-14
        • 1970-01-01
        • 2011-08-25
        相关资源
        最近更新 更多