简体   繁体   English

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

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

EDITED 已编辑

I've been trying to get the simplest way to get a query from different tables, but only showing the quantity according to another table 我一直在尝试获得从不同表中查询的最简单方法,但是仅根据另一张表显示数量

-- Edited: -编辑:

-- I want to create a Pickroute Report -- the pickroute will have an idorder, article, quantity and location -我要创建一个取货路线报告-取货路线将具有idorder,商品,数量和位置

-- Example -例子

-- If I have an order that needs 25 ITEM01 -- I will take 10 from LOC01 and 15 from LOC02 -- All the locatios have a sequence -- Once I complete the 25 I need to update the IDORDER column in SPLITTABLE -如果我的订单需要25个ITEM01-我将从LOC01中获取10个订单,从LOC02中获取15个订单-所有位置都有一个序列-完成25个订单后,我需要更新SPLITTABLE中的IDORDER列

Let me explain 让我解释

I have the following tables 我有下表

SALESORDER table: SALESORDER表:

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

INVENTORY table: 库存表:

  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

What I am trying to get is the following 我想要得到的是以下内容

OPORDER table: 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

Now let me show you what I'm doing to get it done (at least trying to do it). 现在,让我向您展示我正在做些什么(至少尝试这样做)。

Schema : 架构

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)

INVENTORY 库存

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

What I'm doing is: 我正在做的是:

first split into one piece table from the inventory 首先从库存拆分成一张桌子

SPLITTABLE 可分割

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

--Result - 结果

88 rows with quantity 1 --88 Because ITEM01 70 ITEM02 12 and ITEM03 6 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

... until 88 rows(IDORDER is in 0 because it is not asigned yet) ...直到88行(IDORDER处于0,因为尚未分配)

After split I assign an Idorder(On the declare statements this is what I want to avoid) 拆分后,我分配一个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;

--Result - 结果

25 rows from SPLITTABLE with ITEM01 marked as IDORDER 1 来自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

-- The rest of the rows are in 0 because I only select ITEM01 and quantity 25 it --takes only 10 from the LOC01(sequence 1) and 15 from LOC02(sequence 2) -其余的行都在0中,因为我只选择了ITEM01并将其数量定为25-从LOC01(序列1)中只取10个,从LOC02(序列2​​)中取15个

--After changing all the declare statements for each item, order and quantity I can see the result -更改每个项目,订单和数量的所有声明语句后,我可以看到结果

--With this query you get what I want -通过此查询您得到我想要的

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

With these queries I get the information I need but I have some problems 通过这些查询,我可以获得所需的信息,但是我遇到了一些问题

  1. The split part takes all the articles into the SPLITTABLE the problem is when I have an order asking for 1 article but in the inventory for that article has > 1000 it takes a lot of time and resources 拆分的部分将所有文章都放入SPLITTABLE ,问题是当我有一个订单要购买1篇文章,但该文章的库存中有> 1000时,这需要大量时间和资源

  2. Once the split is done, I assign idorder but I had to do it manually for each article and each order 拆分完成后,我分配了idorder但是我必须为每篇文章和每个订单手动进行

I have to thank you in advance for all your comments and help 我必须提前感谢您的所有评论和帮助

In case you need more information, let me know 如果您需要更多信息,请告诉我

You can use cursors. 您可以使用游标。

I used table variables in the example so you'll have to change a code a little bit (remove @) 我在示例中使用了表变量,因此您必须稍微更改一下代码(删除@)

When there is not enough items in the inventory the NULL will be inserted into the LOCATION column, remove this if necessary. 如果库存中没有足够的物品,则NULL将插入到LOCATION列中,如有必要,将其删除。

I didn't add quantity limit, you'll have to make sure that the order can't contain more than the limit because it seems misleading to let the customer order more and then send less than he ordered. 我没有添加数量限制,您必须确保订单中所包含的数量不能超过限制,因为让客户订购更多然后发送的数量少于订购数量似乎具有误导性。 Unless I misunderstood the intent. 除非我误解了意图。

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