按多列排序

时间:2012-05-16 09:07:17

标签: sql sql-server sql-server-2005

我需要按两列排序数据,我该怎么做?

这是我的表:

Name   |  ImpFile   |  ImpTime
Sam      Imp01        2012-05-16 09:54:02.477
Ann      Imp01        2012-05-16 09:54:02.478
Mark     Imp01        2012-05-16 09:54:02.477
John     Import12     2012-05-16 09:55:37.384
Bart     Import12     2012-05-16 09:55:37.387
Sasha    Import12     2012-05-16 09:55:37.385

我需要按ImpTime和ImpName对此表进行排序,它应如下所示:

Name   |  ImpFile   |  ImpTime
         Import12    2012-05-16 09:55:37.387
Bart     Import12    2012-05-16 09:55:37.387
John     Import12    2012-05-16 09:55:37.384
Sasha    Import12    2012-05-16 09:55:37.385
         Imp01       2012-05-16 09:54:02.478
Ann      Imp01       2012-05-16 09:54:02.478
Mark     Imp01       2012-05-16 09:54:02.477
Sam      Imp01       2012-05-16 09:54:02.477

我正在使用此查询,但是当按时间为多行的相同值时,它不按名称对表进行排序,仅按名称排序。

select Name, ImpFile, ImpTime
from people
union
select distinct '', ImpFile, max(ImpTime)
from people 
group by ImpFile
order by ImpTime desc, Name

这个查询给我这样的表:

Name   |  ImpFile   |  ImpTime
         Import12     2012-05-16 09:55:37.387
John     Import12     2012-05-16 09:55:37.384
Bart     Import12     2012-05-16 09:55:37.387
Sasha    Import12     2012-05-16 09:55:37.385
         Imp01        2012-05-16 09:54:02.478
Sam      Imp01        2012-05-16 09:54:02.477
Ann      Imp01        2012-05-16 09:54:02.478
Mark     Imp01        2012-05-16 09:54:02.477

有没有办法同时按这两列排序?

修改的 使用order by ImpFile DESC, ImpTime desc时会发生什么? 它给了我一个像这样的结果表:

Name   |  ImpFile   |  ImpTime
         Import12    2012-05-16 09:55:37.387
         Imp01       2012-05-16 09:54:02.478
Bart     Import12    2012-05-16 09:55:37.387
John     Import12    2012-05-16 09:55:37.384
Sasha    Import12    2012-05-16 09:55:37.385
Ann      Imp01       2012-05-16 09:54:02.478
Mark     Imp01       2012-05-16 09:54:02.477
Sam      Imp01       2012-05-16 09:54:02.477

6 个答案:

答案 0 :(得分:6)

为什么你能这样做:

order by ImpFile DESC, ImpTime desc

不,它不会导致你所展示的内容。结果如下:

        Import12    2012-05-16 09:55:37.387
Bart    Import12    2012-05-16 09:55:37.387
Sasha   Import12    2012-05-16 09:55:37.387
John    Import12    2012-05-16 09:55:37.383
        Imp01       2012-05-16 09:54:02.477
Ann     Imp01       2012-05-16 09:54:02.477
Mark    Imp01       2012-05-16 09:54:02.477
Sam     Imp01       2012-05-16 09:54:02.477

请参阅here以获取示例

修改

我有一个建议给你。也许是这样的:

测试数据

DECLARE @T TABLE(Name VARCHAR(100),ImpFile VARCHAR(100),ImpTime DATETIME)

INSERT INTO @T
    ([Name], [ImpFile], [ImpTime])
VALUES
    ('Sam', 'Imp01', '2012-05-16 09:54:02.477'),
    ('Ann', 'Imp01', '2012-05-16 09:54:02.478'),
    ('Mark', 'Imp01', '2012-05-16 09:54:02.477'),
    ('John', 'Import12', '2012-05-16 09:55:37.384'),
    ('Bart', 'Import12', '2012-05-16 09:55:37.387'),
    ('Sasha', 'Import12', '2012-05-16 09:55:37.385');

<强>查询

;WITH CTE
AS
(   
    SELECT
        ROW_Number() OVER(PARTITION BY  t.[ImpFile] 
                     ORDER BY t.[ImpTime] DESC) AS RowNbr,
        '' AS Name,
        t.ImpFile,
        t.[ImpTime]
    FROM
        @T AS t
)
SELECT
    CTE.Name,
    CTE.ImpFile,
    CTE.[ImpTime],
    0 as SortOrder
FROM
    CTE
WHERE
    CTE.RowNbr=1
UNION ALL
SELECT
    t.Name,
    t.ImpFile,
    t.[ImpTime],
    1 as SortOrder
FROM
    @T AS t
ORDER BY
    ImpFile DESC,SortOrder, ImpTime desc

答案 1 :(得分:5)

获取每个组的领导者并按降序时间对其进行排序:

with grp(Name,ImpFile,TimeGroup,ImpTime) as 
(
  select cast(null as varchar(5)), ImpFile, max(ImpTime) as TimeGroup, 
         max(ImpTime) as ImpTime
  from people 
  group by ImpFile  
)
select * 
from grp
order by TimeGroup desc;

输出:

NAME      IMPFILE   TIMEGROUP                     IMPTIME
(null)    Import12  2012-05-16 09:55:37.3870000   2012-05-16 09:55:37.3870000
(null)    Imp01     2012-05-16 09:54:02.4780000   2012-05-16 09:54:02.4780000

然后将追随者加入领导者并获得领导者的时间(TimeGroup):

with grp(Name,ImpFile,TimeGroup,ImpTime) as 
(
  select cast(null as varchar(5)), ImpFile, max(ImpTime) as TimeGroup, 
         max(ImpTime) as ImpTime
  from people 
  group by ImpFile  

  union all

  select p.Name, p.ImpFile, ldr.TimeGroup, p.ImpTime
  from people p
  inner join grp ldr -- leader
  on ldr.name is null and ldr.ImpFile = p.ImpFile
)
select Name, ImpFile, ImpTime
from grp 
order by TimeGroup desc, Name

输出:

NAME      IMPFILE   IMPTIME
(null)    Import12  2012-05-16 09:55:37.3870000
Bart      Import12  2012-05-16 09:55:37.3870000
John      Import12  2012-05-16 09:55:37.3840000
Sasha     Import12  2012-05-16 09:55:37.3850000
(null)    Imp01     2012-05-16 09:54:02.4780000
Ann       Imp01     2012-05-16 09:54:02.4780000
Mark      Imp01     2012-05-16 09:54:02.4770000
Sam       Imp01     2012-05-16 09:54:02.4770000

查询的逻辑是,我们根据ImpFile将关注者(名字有些人)的时间与其领导者的时间(TimeGroup)对齐。领导者及其粉丝拥有相同的时间组,所以当我们按时间排序时,他们会互相依赖;然后,我们按名称排序

实时测试:http://www.sqlfiddle.com/#!3/c7859/21


如果我们希望小组组长出现在其关注者之后,只需在ORDER BY上提出一个案例:

with grp(Name,ImpFile,TimeGroup,ImpTime) as 
(
  select cast(null as varchar(5)), ImpFile, max(ImpTime) as TimeGroup, 
         max(ImpTime) as ImpTime
  from people 
  group by ImpFile  

  union all

  select p.Name, p.ImpFile, ldr.TimeGroup, p.ImpTime
  from people p
  inner join grp ldr -- leader
  on ldr.name is null and ldr.ImpFile = p.ImpFile
)
select Name, ImpFile, ImpTime
from grp 
order by TimeGroup desc, 

  case 
  when Name is null then 2 -- leader last
  else 1 -- followers first
  end,

  Name

输出:

NAME      IMPFILE   IMPTIME
Bart      Import12  2012-05-16 09:55:37.3870000
John      Import12  2012-05-16 09:55:37.3840000
Sasha     Import12  2012-05-16 09:55:37.3850000
(null)    Import12  2012-05-16 09:55:37.3870000
Ann       Imp01     2012-05-16 09:54:02.4780000
Mark      Imp01     2012-05-16 09:54:02.4770000
Sam       Imp01     2012-05-16 09:54:02.4770000
(null)    Imp01     2012-05-16 09:54:02.4780000

实时测试:http://www.sqlfiddle.com/#!3/c7859/23


工作原理:

with grp(Name,ImpFile,TimeGroup,ImpTime) as 
(
  select cast(null as varchar(5)), ImpFile, max(ImpTime) as TimeGroup, 
         max(ImpTime) as ImpTime
  from people 
  group by ImpFile  

  union all

  select p.Name, p.ImpFile, ldr.TimeGroup, p.ImpTime
  from people p
  inner join grp ldr -- leader
  on ldr.name is null and ldr.ImpFile = p.ImpFile
)
select *
from grp 
order by TimeGroup desc, Name;

输出:

NAME      IMPFILE   IMPTIME                       TIMEGROUP
(null)    Import12  2012-05-16 09:55:37.3870000   2012-05-16 09:55:37.3870000
Bart      Import12  2012-05-16 09:55:37.3870000   2012-05-16 09:55:37.3870000
John      Import12  2012-05-16 09:55:37.3840000   2012-05-16 09:55:37.3870000
Sasha     Import12  2012-05-16 09:55:37.3850000   2012-05-16 09:55:37.3870000
(null)    Imp01     2012-05-16 09:54:02.4780000   2012-05-16 09:54:02.4780000
Ann       Imp01     2012-05-16 09:54:02.4780000   2012-05-16 09:54:02.4780000
Mark      Imp01     2012-05-16 09:54:02.4770000   2012-05-16 09:54:02.4780000
Sam       Imp01     2012-05-16 09:54:02.4770000   2012-05-16 09:54:02.4780000

实时测试:http://www.sqlfiddle.com/#!3/c7859/25

答案 2 :(得分:2)

首先,您应该意识到,使用datetime类型的粒度,SQL Server无法区分2012-05-16 09:55:37.3842012-05-16 09:55:37.385:两者都将存储为2012-05-16 09:55:37.384

考虑到这一点并假设您希望按MAX(ImpTime) DESC排序组以及按ImpTime DESC排序详细信息行,您可以尝试这样的事情:

WITH agg AS (
  SELECT
    *,
    ImpTimeMax = MAX(ImpTime) OVER (PARTITION BY ImpFile),
    rn         = ROW_NUMBER() OVER (PARTITION BY ImpFile ORDER BY ImpTime DESC)
  FROM Table1
)
SELECT
  Name = CASE x.IsAgg WHEN 1 THEN '' ELSE agg.Name END,
  agg.ImpFile,
  agg.ImpTime
FROM agg
  INNER JOIN (SELECT 0 UNION ALL SELECT 1) x (IsAgg) ON x.IsAgg = 0 OR agg.rn = 1
ORDER BY
  agg.ImpTimeMax DESC,  /* the primary order for groups */
  agg.ImpFile    ASC ,  /* in case two or more groups have the same max time */
  x.IsAgg        DESC,  /* the group summary row goes first */
  agg.ImpTime    DESC,  /* or: agg.rn ASC */
  agg.Name       ASC    /* in case two or more people have the same time */

运行on SQL Fiddle时,会为您的示例生成以下输出:

NAME   IMPFILE   IMPTIME
-----  --------  -----------------------
       Import12  2012-05-16 09:55:37.387
Bart   Import12  2012-05-16 09:55:37.387
Sasha  Import12  2012-05-16 09:55:37.385
John   Import12  2012-05-16 09:55:37.384
       Imp01     2012-05-16 09:54:02.478
Ann    Imp01     2012-05-16 09:54:02.478
Mark   Imp01     2012-05-16 09:54:02.477
Sam    Imp01     2012-05-16 09:54:02.477

请注意,我暂时将ImpTime定义为varchar,而不是datetime,只是为了更好地演示,因为,就像我说的那样,{{1}粒度会导致存储的值略有不同(因此产生的输出略有不同)。

答案 3 :(得分:1)

您可能想要擦除毫秒:http://www.sqlfiddle.com/#!3/35065/2

select Name, ImpFile, 

   ImpTimeX = 
      DATEADD(ms, -DATEPART(ms, ImpTime), ImpTime)

from tbl

union

select distinct '', ImpFile, 

   ImpTimeX = 
       MAX(DATEADD(ms, -DATEPART(ms, ImpTime), ImpTime))

from tbl 
group by ImpFile
order by ImpTimeX desc, Name

输出:

NAME           IMPFILE        IMPTIMEX
               Import12       May, 16 2012 09:55:37-0700
Bart           Import12       May, 16 2012 09:55:37-0700
John           Import12       May, 16 2012 09:55:37-0700
Sasha          Import12       May, 16 2012 09:55:37-0700
               Imp01          May, 16 2012 09:54:02-0700
Ann            Imp01          May, 16 2012 09:54:02-0700
Mark           Imp01          May, 16 2012 09:54:02-0700
Sam            Imp01          May, 16 2012 09:54:02-0700

用于清除此处输出的毫秒的技术:SQL Server remove milliseconds from datetime


如果您想保留并显示原始时间,请执行以下操作:http://www.sqlfiddle.com/#!3/35065/1

with a as(

  select Name, ImpFile, 

     ImpTimeX = 
        DATEADD(ms, -DATEPART(ms, ImpTime), ImpTime),

     ImpTime

  from tbl

  union

  select distinct '', ImpFile, 

     ImpTimeX = 
         MAX(DATEADD(ms, -DATEPART(ms, ImpTime), ImpTime)),

     MAX(ImpTime)

  from tbl 
  group by ImpFile

)
select Name, ImpFile, ImpTime
from a
order by ImpTimeX desc, Name

我认为SqlFiddle没有显示毫秒。请在你的Sql Server上尝试第二个查询,我现在正在其他操作系统上,我看不到第二个查询的实际输出


这是第二个查询的输出,日期时间完整,在SSMS上测试:

Name    ImpFile         ImpTime     
        Import12        2012-05-16 09:55:37.3870000
Bart    Import12        2012-05-16 09:55:37.3870000
John    Import12        2012-05-16 09:55:37.3840000
Sasha   Import12        2012-05-16 09:55:37.3850000
        Imp01           2012-05-16 09:54:02.4780000
Ann     Imp01           2012-05-16 09:54:02.4780000
Mark    Imp01           2012-05-16 09:54:02.4770000
Sam     Imp01           2012-05-16 09:54:02.4770000

答案 4 :(得分:0)

看起来order by仅适用于select查询中的第二个union

尝试使用subselect创建临时表格以将order by应用于:

select Name, ImpFile, ImpTime from (
select Name, ImpFile, ImpTime from people
union
select distinct '', ImpFile, max(ImpTime) from people group by ImpFile
) order by ImpTime desc, Name

答案 5 :(得分:0)

您可以通过ImpFile desc,Name

获得所需的输出
select Name, ImpFile, ImpTime
    from dbo.tbl_stack 
    union
    select distinct '', ImpFile, max(ImpTime)
    from dbo.tbl_stack 
    group by ImpFile
    order by ImpFile desc,Name 

这是输出

Name    ImpFile         ImpTime 
        Import12        2012-05-16 09:55:37.387
Bar     Import12        2012-05-16 09:55:37.387
John    Import12        2012-05-16 09:55:37.383
Sasha   Import12        2012-05-16 09:55:37.387
        Imp01       2012-05-16 09:54:02.477
Ann     Imp01       2012-05-16 09:54:02.477
Mark    Imp01       2012-05-16 09:54:02.477
Sam     Imp01           2012-05-16 09:54:02.477