繁体   English   中英

根据另一个表数量显示行<= SQL(T-SQL)

[英]Show rows <= according to another table quantity SQL (T-SQL)

已编辑

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

-编辑:

-我要创建一个取货路线报告-取货路线将具有idorder,商品,数量和位置

-例子

-如果我的订单需要25个ITEM01-我将从LOC01中获取10个订单,从LOC02中获取15个订单-所有位置都有一个序列-完成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

现在,让我向您展示我正在做些什么(至少尝试这样做)。

架构

销售订单

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
);

分裂

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篇文章,但该文章的库存中有> 1000时,这需要大量时间和资源

  2. 拆分完成后,我分配了idorder但是我必须为每篇文章和每个订单手动进行

我必须提前感谢您的所有评论和帮助

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

您可以使用游标。

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

如果库存中没有足够的物品,则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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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