根据另一个表数量SQL(T-SQL)

时间:2018-04-23 15:34:04

标签: sql sql-server tsql

EDITED

我一直在尝试从不同的表中获取查询的最简单方法,但只根据另一个表显示数量

- 编辑:

- 我想创建一个Pickroute报告 - 挑选路线将有一个idorder,文章,数量和位置

- 示例

- 如果我的订单需要25 ITEM01 - 我将从LOC01拿10分,从LOC02拿15分 - 所有的locatios都有一个序列 - 完成25后,我需要更新SPLITTABLE中的IDORDER列

让我解释一下

我有以下表格

SALESORDER 表格:

 IDORDER   ARTICLE   QUANTITY
 ----------------------------
    1      ITEM01       25
    1      ITEM02       10
    2      ITEM01       20
    3      ITEM01       5
    3      ITEM03       4

库存表:

  ARTICLE   QUANTITY   LOCATION   SEQUENCE
  ---------------------------------------
  ITEM01       10       LOC01        1
  ITEM01       30       LOC02        2
  ITEM01       30       LOC03        3
  ITEM02       2        LOC02        2
  ITEM02       10       LOC03        3
  ITEM03       1        LOC01        1
  ITEM03       5        LOC02        2

我想要得到的是以下

OPORDER 表格:

  ARTICLE   QUANTITY   LOCATION   IDORDER
  ----------------------------------------
   ITEM01      10        LOC01       1
   ITEM01      15        LOC02       1
   ITEM02       2        LOC02       1
   ITEM02       8        LOC03       1
   ITEM01      15        LOC02       2
   ITEM01       5        LOC03       2
   ITEM01       5        LOC03       3
   ITEM03       1        LOC01       3
   ITEM03       4        LOC02       3

现在让我告诉你我为完成它所做的工作(至少尝试这样做)。

模式

SALESORDER

DROP TABLE IF EXISTS SALESORDER

CREATE TABLE SALESORDER 
(
     IDORDER INT,
     ARTICLE VARCHAR(50), 
     QUANTITY INT
);

INSERT SALESORDER (IDORDER, ARTICLE, QUANTITY) 
VALUES (1, 'ITEM01', 25), (1, 'ITEM02', 10),
       (2, 'ITEM01', 20), (3, 'ITEM01', 5),
       (3, 'ITEM03', 4)

广告

DROP TABLE IF EXISTS INVENTORY

CREATE TABLE INVENTORY 
(
     ARTICLE VARCHAR(50), 
     QUANTITY INT,
     LOCATION VARCHAR(50),
     SEQUENCE INT
);

INSERT INVENTORY (ARTICLE, QUANTITY,LOCATION,SEQUENCE) 
VALUES ('ITEM01', 10, 'LOC01',1), ('ITEM01', 30, 'LOC02',2),
       ('ITEM01', 30, 'LOC03',3), ('ITEM02', 2, 'LOC02',2),
       ('ITEM02', 10, 'LOC03',3), ('ITEM03', 1, 'LOC01',1),
       ('ITEM03', 5, 'LOC02',2)`

我正在做的是:

首先从库存中拆分成一个表

可裂

DROP TABLE IF EXISTS SPLITTABLE

CREATE TABLE SPLITTABLE 
(
     ARTICLE VARCHAR(50), 
     QUANTITY INT,
     LOCATION VARCHAR(50), 
     IDORDER INT,
     SEQUENCE INT
);

SPLIT

WITH RTE (Vals) AS
(
    SELECT 1 
    UNION ALL

    SELECT 1 + Vals 
    FROM RTE 
    WHERE Vals < 500
)
INSERT INTO SPLITTABLE (ARTICLE, QUANTITY, LOCATION, IDORDER,SEQUENCE) 
    SELECT ARTICLE,1 AS QUANTITY,LOCATIONS,0 AS IDORDER, SEQUENCE
    FROM INVENTORY INV
    INNER JOIN RTE R ON R.Vals <= INV.Quantity
    OPTION (maxrecursion 0);

- 结果

88行,数量为1 --88因为ITEM01 70 ITEM02 12和ITEM03 6

SELECT * FROM SPLITTABLE

ARTICLE QUANTITY    LOCATION    IDORDER SEQUENCE
 ITEM01    1         LOC01         0       1
 ITEM01    1         LOC02         0       2
 ITEM01    1         LOC03         0       3
 ITEM02    1         LOC02         0       2
 ITEM02    1         LOC03         0       3
 ITEM03    1         LOC01         0       1
 ITEM03    1         LOC02         0       2
 ITEM01    1         LOC01         0       1
 ITEM01    1         LOC02         0       2

...直到88行(IDORDER在0中因为它还没有被赋值)

分裂后我分配了一个Idorder(在声明语句中这是我想要避免的)

DECLARE @LIMIT INT =25;
DECLARE @ORDER INT = 1;
DECLARE @ARTICLE VARCHAR(50)='ITEM01';

WITH CTE AS 
(
   SELECT  
       ARTICLE, QUANTITY, LOCATION, IDORDER,
       RUNNINGTOTAL = SUM(QUANTITY) OVER (PARTITION BY ARTICLE ORDER BY 
LOCATION
                                       ROWS UNBOUNDED PRECEDING)
FROM 
    SPLITTABLE
WHERE 
    ARTICLE = @ARTICLE AND IDORDER =0
 ), TOTAL AS
 (
 SELECT 
     ARTICLE, QUANTITY, LOCATION, IDORDER = @ORDER
 FROM 
     CTE 
 WHERE 
     RUNNINGTOTAL <= @LIMIT
 )
 UPDATE CTE 
 SET IDORDER = T.IDORDER 
 FROM TOTAL AS T  
 WHERE RUNNINGTOTAL <= @LIMIT;

- 结果

SPLITTABLE的25行,ITEM01标记为IDORDER 1

SELECT * FROM SPLITTABLE WHERE ARTICLE ='ITEM01' ORDER BY SEQUENCE ASC

ARTICLE QUANTITY    LOCATION    IDORDER SEQUENCE
ITEM01     1          LOC01         1   1
ITEM01     1          LOC01         1   1
ITEM01     1          LOC01         1   1
ITEM01     1          LOC01         1   1
ITEM01     1          LOC01         1   1
ITEM01     1          LOC01         1   1
ITEM01     1          LOC01         1   1
ITEM01     1          LOC01         1   1
ITEM01     1          LOC01         1   1
ITEM01     1          LOC01         1   1
ITEM01     1          LOC02         1   2
ITEM01     1          LOC02         1   2
ITEM01     1          LOC02         1   2
ITEM01     1          LOC02         1   2
ITEM01     1          LOC02         1   2
ITEM01     1          LOC02         1   2
ITEM01     1          LOC02         1   2
ITEM01     1          LOC02         1   2
ITEM01     1          LOC02         1   2
ITEM01     1          LOC02         1   2
ITEM01     1          LOC02         1   2
ITEM01     1          LOC02         1   2
ITEM01     1          LOC02         1   2
ITEM01     1          LOC02         1   2
ITEM01     1          LOC02         1   2

- 其余行为0,因为我只选择ITEM01,数量为25 - 从LOC01(序列1)只有10个,从LOC02(序列2​​)只有15个

- 在更改每个项目,订单和数量的所有声明语句后,我可以看到结果

- 通过此查询,您可以获得我想要的内容

SELECT ARTICLE,SUM(QUANTITY) AS QUANTITY,LOCATION,IDORDER FROM SPLITTABLE 
WHERE IDORDER<>0 GROUP BY ARTICLE,IDORDER,LOCATION ORDER BY IDORDER ASC

通过这些查询,我得到了我需要的信息,但是我遇到了一些问题

  1. 拆分部分会将所有文章纳入SPLITTABLE问题,当我有订单要求1篇文章但该文章的库存中有&gt; 1000需要大量的时间和资源

  2. 完成拆分后,我会指定idorder,但我必须手动为每篇文章和每个订单执行此操作

  3. 我必须提前感谢您的所有意见和帮助

    如果您需要更多信息,请告诉我

1 个答案:

答案 0 :(得分:0)

您可以使用游标。

我在示例中使用了表变量,因此您必须稍微更改一下代码(删除@)

如果清单中没有足够的项目,NULL将被插入LOCATION列,必要时将其删除。

我没有添加数量限制,您必须确保订单不能包含超过限制,因为让客户订购更多然后发送的订单少于他的订单似乎具有误导性。除非我误解了意图。

DECLARE @SALESORDER  TABLE  
(
     IDORDER INT,
     ARTICLE VARCHAR(50), 
     QUANTITY INT
);

INSERT @SALESORDER (IDORDER, ARTICLE, QUANTITY) 
VALUES (1, 'ITEM01', 25), (1, 'ITEM02', 10),(1, 'ITEM14', 1),(2, 'ITEM00', 10),
       (2, 'ITEM01', 70), (3, 'ITEM01', 5),
       (3, 'ITEM03', 4)




DECLARE @INVENTORY TABLE  
(
     ARTICLE VARCHAR(50), 
     QUANTITY INT,
     LOCATION VARCHAR(50)
);

INSERT @INVENTORY (ARTICLE, QUANTITY,LOCATION) 
VALUES ('ITEM01', 10, 'LOC01'), ('ITEM01', 30, 'LOC02'),
       ('ITEM01', 30, 'LOC03'), ('ITEM02', 2, 'LOC02'),
       ('ITEM02', 10, 'LOC03'), ('ITEM03', 1, 'LOC01'),
       ('ITEM03', 5, 'LOC02'), ('ITEM01', 0, 'LOC04')

DECLARE @SPLITTABLE TABLE  
(
     ARTICLE VARCHAR(50), 
     QUANTITY INT,
     LOCATION VARCHAR(50), 
     IDORDER INT
);
---------------------------------------------------------------------------
DECLARE so_cur CURSOR local fast_forward
FOR
SELECT so.ARTICLE,so.QUANTITY,so.IDORDER FROM  @SALESORDER as so 
ORDER BY so.ARTICLE,so.IDORDER
;

DECLARE inv_cur CURSOR local fast_forward
FOR
SELECT inv.ARTICLE,inv.QUANTITY,inv.[LOCATION] FROM  @INVENTORY as inv 
ORDER BY inv.ARTICLE,inv.[LOCATION]
;


declare @so_ARTICLE varchar(50);
declare @so_QUANTITY int; 
declare @so_IDORDER int; 

declare @inv_ARTICLE varchar(50);
declare @inv_QUANTITY int; 
declare @inv_LOCATION varchar(50);

declare @nextOrder bit = 1;
declare @nextInv bit = 1;
declare @outOfInv bit = 0;

open so_cur
open inv_cur

WHILE 1=1
BEGIN

    IF @nextOrder = 1
    BEGIN
        FETCH NEXT from so_cur
        INTO
        @so_ARTICLE, 
        @so_QUANTITY,
        @so_IDORDER
        ;
        SET @nextOrder = 0;
        if @@FETCH_STATUS = -1 break;
    END

    IF @outOfInv = 0 AND @nextInv = 1
    BEGIN
        FETCH NEXT from inv_cur
        INTO
        @inv_ARTICLE, 
        @inv_QUANTITY,
        @inv_LOCATION
        ;
        SET @nextInv = 0;
        if @@FETCH_STATUS = -1 
        BEGIN
            SET @outOfInv = 1;
            PRINT N'NOT ENOUGH ITEMS IN INVENTORY'
        END
    END

    IF @outOfInv = 0 AND @inv_ARTICLE < @so_ARTICLE
    BEGIN
        SET @nextInv = 1;
    END
    ELSE IF @outOfInv = 1 OR @inv_ARTICLE > @so_ARTICLE
    BEGIN
        PRINT N'NOT ENOUGH ITEMS IN INVENTORY, YOU MIGHT WANT TO INSERT LOCATION=NULL TO THE SPLITTABLE';
        INSERT INTO @SPLITTABLE (ARTICLE,QUANTITY,LOCATION,IDORDER) VALUES (@so_ARTICLE,@so_QUANTITY,NULL,@so_IDORDER) 
        SET @nextOrder = 1;
    END
    ELSE
    BEGIN
        IF @so_QUANTITY < @inv_QUANTITY
        BEGIN
            IF @so_QUANTITY >0 
            BEGIN
                INSERT INTO @SPLITTABLE (ARTICLE,QUANTITY,LOCATION,IDORDER) VALUES (@so_ARTICLE,@so_QUANTITY,@inv_LOCATION,@so_IDORDER) 
                SET @inv_QUANTITY -= @so_QUANTITY
            END
            SET @nextOrder = 1;
        END
        ELSE IF @so_QUANTITY = @inv_QUANTITY
        BEGIN
            IF @so_QUANTITY >0 
            BEGIN
                INSERT INTO @SPLITTABLE (ARTICLE,QUANTITY,LOCATION,IDORDER) VALUES (@so_ARTICLE,@so_QUANTITY,@inv_LOCATION,@so_IDORDER)
            END
            SET @nextOrder = 1;
            SET @nextInv = 1;
        END
        ELSE
        BEGIN
            IF @inv_QUANTITY >0
            BEGIN
                INSERT INTO @SPLITTABLE (ARTICLE,QUANTITY,LOCATION,IDORDER) VALUES (@so_ARTICLE,@inv_QUANTITY,@inv_LOCATION,@so_IDORDER)
                SET @so_QUANTITY -= @inv_QUANTITY
            END

            SET @nextInv = 1;
        END
    END

END

CLOSE so_cur;
DEALLOCATE so_cur;
CLOSE inv_cur;
DEALLOCATE inv_cur;
-----------------------------------------------------------------------
SELECT * FROM @SPLITTABLE ORDER BY IDORDER,ARTICLE
相关问题