简体   繁体   中英

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. 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.

Edit

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.

Edit 2

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM