在组

时间:2017-08-01 16:13:14

标签: sql-server tsql

我有一个包含3个字段的表:wk,cor,id

"周"是一周," cor"对来自同一位置的商品进行分组," id"是从仓库中检索的每个项目的ID。

考虑到要检索的特定数量的项目,我必须从每个组中获取几乎相同数量的项目(" cor"代表组)以平衡仓库绩效,尊重周优先级(在进入之前)接下来的一周,前一个必须用尽。)

如果您点击链接,图片可能会清晰: Data sample 行按此顺序排列: 黄色,橙色,绿色,灰色(最后一个以" cor 2&#34开头;因为" cor 1"是第28周最后一次使用)

RES栏(在样本中手工完成)代表我应该采取的正确顺序项目;目前这是通过光标获得的,这是非常慢的,如果可能的话,我想做更好的事情;我尝试过使用窗口函数,cte,递归cte但是无法正常运行。

使用此脚本,您可以拥有相同的表

DECLARE @t TABLE (wk int, cor int, id int)
INSERT INTO @t
     (
         wk
        ,cor
        ,id
     )
VALUES
(28,1,4044534),
(28,1,6778322),
(28,1,7921336),
(28,1,4326390),
(28,2,2669622),
(28,2,6580257),
(28,2,1179795),
(28,3,3980111),
(28,3,2549129),
(28,3,6763533),
(29,1,6023538),
(29,1,8219574),
(29,1,3836858),
(29,2,3355314),
(29,2,148847),
(29,2,8083320),
(29,3,1359966),
(29,3,8746308)

预期结果: 所有字段都是,而 RES字段必须计算并表示项目将被取出的顺序(在下表中说明)。

+----+-----+---------+-----+
| wk | cor |   id    | RES |
+----+-----+---------+-----+
| 28 |   1 | 4044534 |   1 |
| 28 |   1 | 6778322 |   4 |
| 28 |   1 | 7921336 |   7 |
| 28 |   1 | 4326390 |  10 |
| 28 |   2 | 2669622 |   2 |
| 28 |   2 | 6580257 |   5 |
| 28 |   2 | 1179795 |   8 |
| 28 |   3 | 3980111 |   3 |
| 28 |   3 | 2549129 |   6 |
| 28 |   3 | 6763533 |   9 |
| 29 |   1 | 6023538 |  11 |
| 29 |   1 | 8219574 |  14 |
| 29 |   1 | 3836858 |  17 |
| 29 |   2 | 3355314 |  12 |
| 29 |   2 |  148847 |  15 |
| 29 |   2 | 8083320 |  18 |
| 29 |   3 | 1359966 |  13 |
| 29 |   3 | 8746308 |  16 |
+----+-----+---------+-----+

算法是这样的:

  1. 必须首先考虑较旧的一周(在样本中,第28周必须完成,然后才从第29周开始)
  2. 项目必须在" cor" s中同等地重新分配,因此如果需要10个项目,它们必须如此出现:3来自cor1,3来自cor2,3来自cor3。最后一个可能来自任何一个,因为10不能被3整除,obv
  3. 如果需要11项;第28周只包含10个项目,因此最后一个项目将从第29周开始,原则相同:即使周数变化,也可以在cors之间平均分配出口。如果第28周的最后一篇文章来自第1卷,第29周的下一篇文章将取自第2期

2 个答案:

答案 0 :(得分:3)

这能解决您的问题吗?

DROP TABLE IF EXISTS #temp
DROP TABLE IF EXISTS #temp2

CREATE TABLE #temp (idx INT PRIMARY KEY IDENTITY(1,1), wk int, cor int, id int)
INSERT INTO #temp
VALUES
(28,1,4044534),
(28,1,6778322),
(28,1,7921336),
(28,1,4326390),
(28,2,2669622),
(28,2,6580257),
(28,2,1179795),
(28,3,3980111),
(28,3,2549129),
(28,3,6763533),
(29,1,6023538),
(29,1,8219574),
(29,1,3836858),
(29,2,3355314),
(29,2,148847),
(29,2,8083320),
(29,3,1359966),
(29,3,8746308)

SELECT wk, cor, id
    , ROW_NUMBER() OVER (ORDER BY wk, RES, idx) as RES
FROM (
    SELECT  idx
        ,   wk
        ,   cor
        ,   id
        ,   ROW_NUMBER() OVER (PARTITION BY wk, cor ORDER BY cor) AS RES
    FROM    #temp
    ) AS t
ORDER BY idx

答案 1 :(得分:0)

您的测试数据中没有正确的信息以支持所需的输出。 但是,如果您有一个表示插入顺序的标识列,则可以使用以下内容...

WITH cte_RankOrder AS (
        SELECT 
            t.rn, t.wk, t.cor, t.id,
            RankOrder = DENSE_RANK() OVER (PARTITION BY t.wk, t.cor ORDER BY t.rn, t.wk)
        FROM
            @t t
        )
SELECT 
    ro.rn, ro.wk, ro.cor, ro.id,
    RES = ROW_NUMBER() OVER (ORDER BY wk, ro.RankOrder, ro.cor)
FROM
    cte_RankOrder ro
ORDER BY ro.rn;

结果...

rn          wk          cor         id          RES
----------- ----------- ----------- ----------- --------------------
1           28          1           4044534     1
2           28          1           6778322     4
3           28          1           7921336     7
4           28          1           4326390     10
5           28          2           2669622     2
6           28          2           6580257     5
7           28          2           1179795     8
8           28          3           3980111     3
9           28          3           2549129     6
10          28          3           6763533     9
11          29          1           6023538     11
12          29          1           8219574     14
13          29          1           3836858     17
14          29          2           3355314     12
15          29          2           148847      15
16          29          2           8083320     18
17          29          3           1359966     13
18          29          3           8746308     16
HTH,Jason