[英]Assign rownumber in SQL grouped on value and n rows per rownumber
I am trying to generate a report with 3 rows per page for each order number using the following SQL. 我正在尝试使用以下SQL生成每个订单号每页3行的报告。 As you can see from the results the fields Actual & Expected do not match up.
从结果中可以看到,“实际”和“期望”字段不匹配。
Any help would be appreciated. 任何帮助,将不胜感激。
set nocount on
DECLARE @Orders TABLE (Expected int, OrderNumber INT, OrderDetailsNumber int)
Insert into @orders values (0,1,1)
Insert into @orders values (0,1,2)
Insert into @orders values (0,1,3)
Insert into @orders values (1,1,4)
Insert into @orders values (2,2,5)
Insert into @orders values (2,2,6)
Insert into @orders values (2,2,7)
Insert into @orders values (3,2,8)
Insert into @orders values (3,2,9)
select cast(((row_number() over( order by OrderNumber)) -1) /3 as int) as [Actual]
,*
from @orders
Actual Expected OrderNumber OrderDetailsNumber
----------- ----------- ----------- ------------------
0 0 1 1
0 0 1 2
0 0 1 3
1 1 1 4
1 2 2 5
1 2 2 6
2 2 2 7
2 3 2 8
2 3 2 9
Right, after a couple of edits I have the final answer: 是的,经过几次编辑后,我得到了最终答案:
SELECT DENSE_RANK() OVER (Order BY OrderNumber, floor(RowNumber/3)) - 1 AS Actual,
Expected,
OrderNumber,
OrderDetailsNumber
FROM
(
SELECT *,
ROW_NUMBER() OVER (
PARTITION BY OrderNumber
ORDER BY OrderDetailsNumber
) - 1 AS RowNumber
FROM @Orders
) RowNumberTable
Gives the result (with extra rows for testing): 给出结果(有更多行用于测试):
Actual Expected OrderNumber OrderDetailsNumber
-------------------- ----------- ----------- ------------------
0 0 1 1
0 0 1 2
0 0 1 3
1 1 1 4
1 1 1 12
2 2 2 5
2 2 2 6
2 2 2 7
3 3 2 8
3 3 2 9
3 4 2 11
4 3 2 27
5 5 3 10
This only works where OrderDetailsNumber is unique such that the result is deterministic. 这仅在OrderDetailsNumber是唯一的以使结果具有确定性的情况下有效。
I've now got the complete code working, however the dependence on OrderDetailsNumber being in order is very iffy, hopefully you can test and edit as required. 现在,我已经完成了完整的代码,但是对OrderDetailsNumber的依赖非常复杂,希望您可以根据需要进行测试和编辑。
I've put the 'golfed' version in the main answer. 我已经在主要答案中加入了“打高尔夫球”的版本。
WITH FirstCTE AS
(
SELECT
OrderNumber,
OrderDetailsNumber,
Expected,
ROW_NUMBER() OVER (
PARTITION BY OrderNumber
ORDER BY OrderDetailsNumber
) - 1 AS RowNumber
FROM @Orders
)
, SecondCTE AS
(
SELECT OrderDetailsNumber as odn,
floor(RowNumber/3) as page_for_order_number,
DENSE_RANK() OVER (Order BY OrderNumber, floor(RowNumber/3)) - 1 AS Actual
FROM FirstCTE
)
SELECT c2.page_for_order_number,
c1.RowNumber,
C2.Actual,
c1.Expected,
c1.OrderNumber,
c1.OrderDetailsNumber
FROM FirstCTE AS c1
INNER JOIN SecondCTE AS c2
on c2.odn = c1.OrderDetailsNumber
This strikes me as a bit of a hack, but it works... Divide the row_number() by 3, and use CEILING to get the smallest integer greater than or equal to the result of that division. 这让我有些吃惊,但是它可以工作...将row_number()除以3,然后使用CEILING获得大于或等于该除法结果的最小整数。
select row_number() over( order by OrderNumber) as [Actual],
cast (row_number() over(order by ordernumber) as decimal(5,1)) / 3,
CEILING(cast (row_number() over(order by ordernumber) as decimal(5,1)) / 3)as GRPR,
*
from @orders
EDIT: Dang it, can never get results to line up. 编辑:晃来晃去,永远无法获得结果排队。 The 3rd column in the result set is your "page number".
结果集中的第三列是您的“页码”。 Which yields:
产生:
Actual (No column name) PG_NBR Expected OrderNumber OrderDetailsNumber
1 0.333333 1 0 1 1
2 0.666666 1 0 1 2
3 1.000000 1 0 1 3
4 1.333333 2 1 1 4
5 1.666666 2 2 2 5
6 2.000000 2 2 2 6
7 2.333333 3 2 2 7
8 2.666666 3 3 2 8
9 3.000000 3 3 2 9
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.