简体   繁体   English

在SQL中按值分组分配行号,每个行号分配n行

[英]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是唯一的以使结果具有确定性的情况下有效。

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. 现在,我已经完成了完整的代码,但是对OrderDetailsNumber的依赖非常复杂,希望您可以根据需要进行测试和编辑。

Edit 2 编辑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. 这让我有些吃惊,但是它可以工作...将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.

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