【问题标题】:Generate DENSE_RANK() without using order by clause - SQL Server在不使用 order by 子句的情况下生成 DENSE_RANK() - SQL Server
【发布时间】:2018-10-04 05:44:45
【问题描述】:

我是SQL Server 的新手,任何人都可以指导我查询,这对我很有帮助。

我需要像这个例子一样生成排名:

Report No               Rank 
----------------------------
18  3229                 1
89-0119-87               2
180261292                3
180261292                3
18  3107                 4
18A 7     A06            5
T18002415                6
T18002415                6
T18002415                6
0000000018-519           7
0000000018-519           7
0000000018-519           7
0000000018-519           7
0000000018-655           8
000000018-1002           9
000000018-1002           9
000000018-1002           9
000000018-5712           10

如果我使用

生成排名
DENSE_RANK() OVER(ORDER BY ReportNo DESC)

那么我没有得到所需的输出。你能指导我吗?如上例所示,如何生成排名?

【问题讨论】:

  • 请解释逻辑。为什么89-0119-87介于18 3229180261292之间
  • 你试试我的答案吗?它有帮助还是您需要其他什么?
  • 数据没有顺序。除非您指定 order by,否则您不能期望它以相同的顺序返回 - 因此尝试实现没有 order by 的排名是没有意义的。
  • @uzi 这种类型的报告没有逻辑,不,我正在从不同的站点获取数据
  • 如果你找不到合适的东西放在ORDER BY 子句中来生成你正在寻找的输出,那么你的要求是不明智的——或者你缺少所需的数据填充 ORDER BY 或者当您无法自己将其表达到 ORDER BY 子句中时,您期望服务器神奇地“知道我的意思”。一个 ORDER BY 子句被欺骗接受一个常量(正如 Dinesh 的回答所示)只是举手并希望服务器会产生一些有时会产生令你满意的结果。

标签: sql-server database tsql window-functions


【解决方案1】:

我看不到 Report No 的排序逻辑。由于它是自定义订单,请创建包含所需订单 Report NoRankanotherTable(临时表或表变量)。

Report No           Rank 
18  3229                 1
89-0119-87               2
180261292                3
18  3107                 4
18A 7     A06            5
T18002415                6
0000000018-519           7
0000000018-655           8
000000018-1002           9
000000018-5712           10

然后

SELECT thisTable.ReportNo, anotherTable.[Rank]
FROM thisTable
INNER JOIN anotherTable ON thisTable.ReportNo = anotherTable.ReportNo

【讨论】:

  • 我投了赞成票(因为它是解决问题的方法),但是直接将此排序列添加到表中会更容易 - 可能... :-D
  • @Partita,你能试试这个吗?
【解决方案2】:

试试这个:

DECLARE @Tab TABLE(Report_No VARCHAR(100))

INSERT INTO @Tab VALUES('18  3229')
INSERT INTO @Tab VALUES('89-0119-87')
INSERT INTO @Tab VALUES('180261292')
INSERT INTO @Tab VALUES('180261292')
INSERT INTO @Tab VALUES('18  3107')
INSERT INTO @Tab VALUES('18A 7     A06')
INSERT INTO @Tab VALUES('T18002415')
INSERT INTO @Tab VALUES('T18002415')
INSERT INTO @Tab VALUES('T18002415')
INSERT INTO @Tab VALUES('0000000018-519')
INSERT INTO @Tab VALUES('0000000018-519')
INSERT INTO @Tab VALUES('0000000018-519')
INSERT INTO @Tab VALUES('0000000018-519')
INSERT INTO @Tab VALUES('0000000018-655')
INSERT INTO @Tab VALUES('000000018-1002')
INSERT INTO @Tab VALUES('000000018-1002')
INSERT INTO @Tab VALUES('000000018-1002')
INSERT INTO @Tab VALUES('000000018-5712')

SELECT *
    ,ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) RN
INTO #temp
FROM @Tab T1

SELECT T1.Report_No
    ,SUM(CASE WHEN T1.Report_No = T2.Report_No THEN 0 ELSE 1 END) OVER(ORDER BY T1.rn)[Rank]
FROM #temp T1
LEFT JOIN #temp T2 ON T1.rn = T2.rn+1

DROP TABLE #temp

输出:

Report_No       Rank
18  3229        1
89-0119-87      2
180261292       3
180261292       3
18  3107        4
18A 7     A06   5
T18002415       6
T18002415       6
T18002415       6
0000000018-519  7
0000000018-519  7
0000000018-519  7
0000000018-519  7
0000000018-655  8
000000018-1002  9
000000018-1002  9
000000018-1002  9
000000018-5712  10

【讨论】:

  • @PawanKumar,尝试更新的答案。
  • @DineshDB 我已经尝试过您的解决方案,它正在运行,谢谢但是我没有大量数据,因为它是增加查询执行时间超过 5 秒您对此有任何想法
  • @ParitaNavadiya,我能理解。但是您的桌子没有要订购的列,所以我们没有办法。如果存在任何用于排序的列,则应该是可能的。
  • @DineshDB 我的输出表按 ID 字段排序
  • ORDER BY(SELECT NULL) 基本上是在欺骗优化器接受它通常应该拒绝的查询(与将被拒绝的ORDER BY NULL 相比)。由于这个原因,整个事情是不确定的,所以虽然 有时 它可能看起来“起作用”,但它只是巧合地编程。
【解决方案3】:

使用分组方式:

WITH data as (
    SELECT '18  3229' col1 UNION ALL
    SELECT '89-0119-87' UNION ALL
    SELECT '180261292' UNION ALL
    SELECT '180261292' UNION ALL
    SELECT '18  3107' UNION ALL
    SELECT '18A 7     A06' UNION ALL
    SELECT 'T18002415' UNION ALL
    SELECT 'T18002415' UNION ALL
    SELECT 'T18002415' UNION ALL
    SELECT '0000000018-519' UNION ALL
    SELECT '0000000018-519' UNION ALL
    SELECT '0000000018-519' UNION ALL
    SELECT '0000000018-519' UNION ALL
    SELECT '0000000018-655' UNION ALL
    SELECT '000000018-1002' UNION ALL
    SELECT '000000018-1002' UNION ALL
    SELECT '000000018-1002' UNION ALL
    SELECT '000000018-5712'), 
data_with_rownumber as (
    SELECT *, row_number() over (order by (SELECT 1)) rownum from data
), grouped as (
    SELECT col1, min(rownum) rank from data_with_rownumber group by col1)
select d.col1, DENSE_RANK() over (order by rank) from data d inner join grouped gr on d.col1 = gr.col1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-12
    • 1970-01-01
    • 2022-07-04
    • 1970-01-01
    相关资源
    最近更新 更多