根据计数均匀分布顺序SQL结果

时间:2018-09-27 21:34:36

标签: sql tsql ssms

我有需要分解为项目范围的SQL结果,并且计数在多个任务之间平均分配。什么是这样做的好方法?

我的数据如下。

+------+-------+----------+
| Item | Count | ItmGroup |
+------+-------+----------+
| 1A   |   100 |        1 |
| 1B   |    25 |        1 |
| 1C   |     2 |        1 |
| 1D   |     6 |        1 |
| 2A   |    88 |        2 |
| 2B   |    10 |        2 |
| 2C   |   122 |        2 |
| 2D   |    12 |        2 |
| 3A   |     4 |        3 |
| 3B   |   103 |        3 |
| 3C   |     1 |        3 |
| 3D   |    22 |        3 |
| 4A   |    55 |        4 |
| 4B   |    42 |        4 |
| 4C   |   100 |        4 |
| 4D   |     1 |        4 |
+------+-------+----------+

Item =商品代码。 Count =在这种情况下,它确定了商品的受欢迎程度。如果需要,可以将其用于RANK项目。 ItmGroup-这是Itm列的父值。项目包含在组中。

这与我已经查看过的其他类似问题的不同之处在于,我需要确定的范围不能超出表中显示的顺序。我们可以执行从A1到B3的项目范围,换句话说,它们可以跨越ItmGroups,但是它们必须按Item保持字母数字顺序。

预期结果将是均匀分布总计数的项目范围。

+------+-------+----------+
| FrItem | ToItem | TotCount|
+------+-------+----------+
| 1A   |   2D  |      134 |
| 3A   |   3D  |      130 |
(etc)

2 个答案:

答案 0 :(得分:1)

只要您对粗略的估算感到满意,就可以将数据分成两组。

第一个组将始终具有尽可能多的记录,但 不超过 个总数的一半(第二组将拥有其余记录)

WITH
  cumulative AS
(
  SELECT
    *,
    SUM([Count]) OVER (ORDER BY Item)   AS cumulativeCount,
    SUM([Count]) OVER ()                AS totalCount
  FROM
    yourData
)
SELECT
  MIN(item)    AS frItem,
  MAX(item)    AS toItem,
  SUM([Count]) AS TotCount
FROM
  cumulative
GROUP BY
  CASE WHEN cumulativeCount <= totalCount / 2 THEN 0 ELSE 1 END
ORDER BY
  CASE WHEN cumulativeCount <= totalCount / 2 THEN 0 ELSE 1 END

要将数据分成5部分,这很相似...

GROUP BY
  CASE WHEN cumulativeCount <= totalCount * 1/5 THEN 0
       WHEN cumulativeCount <= totalCount * 2/5 THEN 1
       WHEN cumulativeCount <= totalCount * 3/5 THEN 2
       WHEN cumulativeCount <= totalCount * 4/5 THEN 3
                                                ELSE 4 END

根据您的数据,这不一定是理想的

 Item | Count       GroupAsDefinedAbove   IdealGroup
------+-------
  1A  |   4              1                  1
  2A  |   5              2                  1
  3A  |   8              2                  2

如果您想要使两组的尺寸尽可能接近的东西,那就复杂得多。

答案 1 :(得分:0)

与接受的答案相同,除了在WITHcumulativeCte中声明批号和在select语句中添加一个附加值以防止剩余。

  DECLARE @BatchCount NUMERIC(4,2) = 5.00;

    WITH
      cumulativeCte AS
    (
      SELECT
        *,
        SUM(r.[Count]) OVER (ORDER BY Item)   AS cumulativeCount,
        SUM(r.[Count]) OVER ()                AS totalCount
        ,CEILING(SUM(r.[Count]) OVER (ORDER BY IM.MMITNO ASC) / (SUM(r.[Count]) OVER () / @BatchCount)) AS BatchNo
      FROM
        records r
    )
    SELECT
      MIN(c.Item)    AS frItem,
      MAX(c.Item)    AS toItem,
      SUM(c.[Count]) AS TotCount,
      c.BatchNo

    FROM
      cumulativeCte c
    GROUP BY
      c.BatchNo
    ORDER BY
      c.BatchNo