【问题标题】:ORDER BY or GROUP BY based on three columns in SQL Server基于 SQL Server 中的三列的 ORDER BY 或 GROUP BY
【发布时间】:2016-01-07 05:23:54
【问题描述】:

我有一张这样的桌子..

Priority | Amount | Case
P1       | 100    | 1
P1       | 200    | 2
P1       | 300    | 1
P3       | 400    | 3

我想先按PriorityAmount(降序)排序,然后按Case 排序,看起来像这样。

Priority | Amount | Case
P1       | 300    | 1
P1       | 100    | 1
P1       | 200    | 2
P3       | 400    | 3

如果我使用ORDER BY Priority, Amount DESC, Case,那么它会返回这个。其中Case 未根据Amount 的最高值分组在一起。

Priority | Amount | Case
P1       | 300    | 1
P1       | 200    | 2
P1       | 100    | 1
P3       | 400    | 3

编辑:为清楚起见再添加一条记录:

Priority | Amount | Case
P1       | 100    | 1
P1       | 200    | 2
P1       | 300    | 1
P1       | 200    | 0   << New record
P3       | 400    | 3

这应该返回为:

Priority | Amount | Case
P1       | 300    | 1
P1       | 100    | 1
P1       | 200    | 0
P1       | 200    | 2
P3       | 400    | 3

首先它按Priority 分组,其中按最高Amount 排序,然后在Amount 中按Case 分组

【问题讨论】:

  • 你想要的输出似乎需要这个:ORDER BY Priority, Case, Amount DESC我在这里遗漏了什么吗?
  • 嗨蒂姆。我已经编辑了我的问题以提供更清晰的图片。请仔细研究并提出解决方案。这不是一个简单的 ORDER BY :)
  • 很遗憾,现在画面更不清晰了。除了Priority 列之外,您的预期输出似乎没有在任何列上排序。
  • @Damien_The_Unbeliever 在Amount 并列的情况下,Case升序 顺序排序。非常好的捕获(难怪你超过 100K)。
  • @Damien_The_Unbeliever - 非常好的收获 - ((难怪你超过 100K) :-D

标签: sql sql-server group-by sql-order-by


【解决方案1】:

您需要使用窗口聚合来找到每个Case 中的最高 数量,然后使用那个 进行排序:

declare @t table ([Priority] varchar(19) not null,Amount int not null, [Case] int not null)
insert into @t ([Priority],Amount,[Case]) values
('P1',100,1),
('P1',200,2),
('P1',300,1),
('P1',200,0),
('P3',400,3)

select
    *
from
    (
        select *,MAX(Amount) OVER (PARTITION BY [Case]) as mAmount
        from @t
    ) t
order by [Priority],mAmount desc,[Case],Amount desc

结果:

Priority            Amount      Case        mAmount
------------------- ----------- ----------- -----------
P1                  300         1           300
P1                  100         1           300
P1                  200         0           200
P1                  200         2           200
P3                  400         3           400

另外,请考虑重命名您的某些列 - 我不得不将两个列括在 [] 括号中,因为它们是保留字。通常最好完全避免保留字。

【讨论】:

  • 是的!这是做的! :)
【解决方案2】:
CREATE TABLE SHANKATABLE (PRIORITY VARCHAR(2), AMOUNT INT, [CASE] INT)
INSERT INTO SHANKATABLE VALUES('P1',   100 , 1)
INSERT INTO SHANKATABLE VALUES ('P1',   200 , 2)
INSERT INTO SHANKATABLE VALUES ('P1',   300 , 1)
INSERT INTO SHANKATABLE VALUES ('P3',   400 , 3)

要获得第一个结果,只需使用以下查询,

基于Damien_The_Unbeliever 答案,我只是在更新我的答案。

SELECT PRIORITY,[CASE],AMOUNT
FROM   (
           SELECT PRIORITY,[CASE],AMOUNT,MAX(Amount) OVER(PARTITION BY [Case]) AS mAmount
           FROM   SHANKATABLE
       ) Temp
ORDER BY
       [Priority],mAmount DESC,[Case],Amount DESC

updated sql fiddle demo

【讨论】:

  • 感谢 Rajesh 的快速回复。我想我过度简化了我的表格和问题。让我们在此表中再添加一行INSERT INTO SHANKATABLE VALUES ('P1', 200 , 0) 现在Case 0 将出现在表的顶部,但它的Amount 值小于Priority P1 中的最大值。您的代码将返回 PRIORITY | AMOUNT | CASEP1 | 200 | 0 P1 | 300 | 1 P1 | 100 | 1 P1 | 200 | 2 P3 | 400 | 3 我正在寻找 PRIORITY | AMOUNT | CASE P1 | 300 | 1 P1 | 100 | 1 P1 | 200 | 0 P1 | 200 | 2 P3 | 400 | 3
【解决方案3】:

我想你想要这个

select * from tablename ORDER BY Priority, [case] , Amount DESC

【讨论】:

    【解决方案4】:

    标识符不能是 SQL 中的保留关键字,不能有嵌入空格,并且不能包含补充字符。

    必须对不符合这些规则的标识符进行分隔。

    例如,名为 2006 的属性被视为不规则标识符,因为它以数字开头,因此必须用“2006”或 [2006] 分隔。像 y2006 这样的常规标识符可以在没有分隔符的情况下引用,就像 y2006 一样,或者它可以是可选的,带有分隔符。您可能不希望对常规标识符进行分隔,因为分隔符会使代码混乱。

    【讨论】:

    • 谢谢埃里克。然而,这只是我使用的一个示例名称。我的实际表不包含相同的列名称
    【解决方案5】:

    试试这个:-

    select [PRIORITY],[amount],[case] from Table
    order by [PRIORITY], [CASE] asc,AMOUNT desc
    

    【讨论】:

    • 谢谢 GKarya。默认情况下,SQL 使用升序排序而不使用它。但是我确实尝试过,但是没有用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-31
    • 2011-07-18
    相关资源
    最近更新 更多