记录的更新取决于sql中的数量

时间:2017-01-23 04:31:40

标签: sql sql-server

我有2个这样的查询:

select  
    F_In_Out_Date ,
    F_QTY, F_lot_number, F_BillOf_entryNumber 
from 
    T_Tra_Transaction 
where 
    F_lot_number = '160427A161' 
    and F_Stock_Type = 'IN'

select  
    F_In_Out_Date ,
    F_QTY, F_lot_number, F_BillOf_entryNumber 
from 
    T_Tra_Transaction 
where 
    F_lot_number = '160427A161' 
    and F_Stock_Type = 'out'

我的输出如下:

enter image description here

我的第一个查询显示In Qty,我的第二个查询显示OUT数量取决于我的BOE编号。在我的结果中,首先100个数量来自Billof条目号14-2-4-15451983,因此在我的状态查询中,我需要使用以上条目号码更新前100个数量。另外70个数量需要更新其他条目号(14-2-4-15546475)。我怎样才能做到这一点?

我做了一个查询,但是用第一个条目号更新所有记录。

update tout
set F_BillOf_entryNumber = tin.F_BillOf_entryNumber 
from 
    (select 
         F_QTY, F_lot_number, F_BillOf_entryNumber, 
         rn = row_number() over (partition by F_QTY, F_lot_number order by F_In_Out_Date desc)
     from 
         T_Tra_Transaction 
     where 
         F_Stock_Type = 'out') tout
join 
    (select 
         F_QTY, F_lot_number, F_BillOf_entryNumber,
         rn = row_number() over (partition by F_QTY, F_lot_number order by F_In_Out_Date desc)
     from 
         T_Tra_Transaction 
     where 
         F_Stock_Type = 'IN') tin on tout.F_lot_number = tin.F_lot_number

2 个答案:

答案 0 :(得分:0)

它有些复杂。你需要一个递归的CTE才能实现它。

上述架构:

CREATE TABLE #T_TRA_TRANSACTION (F_Id INT IDENTITY PRIMARY KEY
,F_IN_OUT_DTE DATETIME
,F_QTY INT
,F_LOT_NUMBER VARCHAR(50)
,F_BILLOF_ENTRYNUMBER VARCHAR(50)
,F_STOCK_TYPE VARCHAR(10))


INSERT INTO #T_TRA_TRANSACTION

SELECT '2016-05-31',15,'160427A161','14-2-4-15451983','IN'
UNION ALL
SELECT '2016-05-31',5,'160427A161','14-2-4-15451983','IN'
UNION ALL
SELECT '2016-08-02',10,'160427A161','14-2-4-15546475','IN'
UNION ALL
SELECT '2016-08-02',10,'160427A161','14-2-4-15546475','IN'
UNION ALL
SELECT '2016-08-02',5,'160427A161','14-2-4-15546475','IN'

UNION ALL
SELECT '2016-08-14',5,'160427A161','14-2-4-15546475','OUT'
UNION ALL
SELECT '2016-08-14',5,'160427A161','14-2-4-15546475','OUT'
UNION ALL
SELECT '2016-08-14',5,'160427A161','14-2-4-15546475','OUT'
UNION ALL
SELECT '2016-08-14',5,'160427A161','14-2-4-15546475','OUT'
UNION ALL
SELECT '2016-08-18',5,'160427A161','14-2-4-15546475','OUT'
UNION ALL
SELECT '2016-08-18',5,'160427A161','14-2-4-15546475','OUT'
UNION ALL
SELECT '2016-08-18',5,'160427A161','14-2-4-15546475','OUT'
UNION ALL
SELECT '2016-08-18',5,'160427A161','14-2-4-15546475','OUT'
UNION ALL
SELECT '2016-08-18',5,'160427A161','14-2-4-15546475','OUT'

然后尝试以下查询。我已经添加了每个CTE的中间结果,以了解我们从中获取的内容

;WITH CTE_BILL_WISE AS(
SELECT 
ROW_NUMBER() OVER(ORDER BY (SELECT 1)) SNO_IN
,SUM(F_QTY) IN_QTY
, F_BILLOF_ENTRYNUMBER 
FROM 
    #T_TRA_TRANSACTION 
WHERE 
    F_LOT_NUMBER = '160427A161' 
    AND F_STOCK_TYPE = 'IN' 
GROUP BY F_BILLOF_ENTRYNUMBER 

/* RESULT OF CTE_BILL_WISE
+--------+--------+----------------------+
| SNO_IN | IN_QTY | F_BILLOF_ENTRYNUMBER |
+--------+--------+----------------------+
|      1 |     20 | 14-2-4-15451983      |
|      2 |     25 | 14-2-4-15546475      |
+--------+--------+----------------------+

*/

)
,CTE_BILL_QTY_RANGE AS
(
    SELECT SNO_IN, F_BILLOF_ENTRYNUMBER, 0 START_QTY ,IN_QTY AS END_QTY  FROM CTE_BILL_WISE WHERE SNO_IN = 1
    UNION ALL
    SELECT C4.SNO_IN+1,C.F_BILLOF_ENTRYNUMBER, C4.END_QTY+1,C4.END_QTY+ C.IN_QTY FROM CTE_BILL_QTY_RANGE C4
    INNER JOIN CTE_BILL_WISE C ON C4.SNO_IN+1 = C.SNO_IN

    /* RESULT OF CTE_BILL_QTY_RANGE
    +--------+----------------------+-----------+---------+
    | SNO_IN | F_BILLOF_ENTRYNUMBER | START_QTY | END_QTY |
    +--------+----------------------+-----------+---------+
    |      1 | 14-2-4-15451983      |         0 |      20 |
    |      2 | 14-2-4-15546475      |        21 |      45 |
    +--------+----------------------+-----------+---------+
    */

)

,CTE_OUT_TYPE AS
(
    SELECT   F_Id ,
    F_QTY
    ,ROW_NUMBER() OVER(ORDER BY  F_Id) SNO_OUT
    FROM #T_TRA_TRANSACTION 
    WHERE F_LOT_NUMBER = '160427A161' 
    AND F_STOCK_TYPE = 'OUT' 

    /* RESULT OF CTE_OUT_TYPE
    +------+-------+---------+
    | F_Id | F_QTY | SNO_OUT |
    +------+-------+---------+
    |    6 |     5 |       1 |
    |    7 |     5 |       2 |
    |    8 |     5 |       3 |
    |    9 |     5 |       4 |
    |   10 |     5 |       5 |
    |   11 |     5 |       6 |
    |   12 |     5 |       7 |
    |   13 |     5 |       8 |
    |   14 |     5 |       9 |
    +------+-------+---------+
    */

)
,CTE_OUT_QTY_SUM AS
(
    SELECT SNO_OUT, F_Id,F_QTY  FROM CTE_OUT_TYPE WHERE SNO_OUT = 1
    UNION ALL
    SELECT  C2.SNO_OUT,  C2.F_Id,F_QTY = C3.F_QTY+C2.F_QTY  FROM CTE_OUT_QTY_SUM C3
    INNER JOIN CTE_OUT_TYPE C2 ON C3.SNO_OUT+1 = C2.SNO_OUT 

    /* RESULT OF CTE_OUT_QTY_SUM
    +---------+------+-------+
    | SNO_OUT | F_Id | F_QTY |
    +---------+------+-------+
    |       1 |    6 |     5 |
    |       2 |    7 |    10 |
    |       3 |    8 |    15 |
    |       4 |    9 |    20 |
    |       5 |   10 |    25 |
    |       6 |   11 |    30 |
    |       7 |   12 |    35 |
    |       8 |   13 |    40 |
    |       9 |   14 |    45 |
    +---------+------+-------+
    */

)

SELECT C3.F_Id, C4.F_BILLOF_ENTRYNUMBER FROM CTE_OUT_QTY_SUM C3
INNER JOIN CTE_BILL_QTY_RANGE C4 ON  C3.F_QTY  BETWEEN C4.START_QTY AND C4.END_QTY

    /* RESULT OF FINAL CTE
    +------+----------------------+
    | F_Id | F_BILLOF_ENTRYNUMBER |
    +------+----------------------+
    |    6 | 14-2-4-15451983      |
    |    7 | 14-2-4-15451983      |
    |    8 | 14-2-4-15451983      |
    |    9 | 14-2-4-15451983      |
    |   10 | 14-2-4-15546475      |
    |   11 | 14-2-4-15546475      |
    |   12 | 14-2-4-15546475      |
    |   13 | 14-2-4-15546475      |
    |   14 | 14-2-4-15546475      |
    +------+----------------------+
    */

您可以将最后一个选择更改为更新,如

UPDATE #T_TRA_TRANSACTION SET #T_TRA_TRANSACTION.F_BILLOF_ENTRYNUMBER = C4.F_BILLOF_ENTRYNUMBER
FROM CTE_OUT_QTY_SUM C3
INNER JOIN CTE_BILL_QTY_RANGE C4 ON  C3.F_QTY  BETWEEN C4.START_QTY AND C4.END_QTY
INNER JOIN #T_TRA_TRANSACTION ON  #T_TRA_TRANSACTION.F_Id = C3.F_Id

答案 1 :(得分:0)

我不确定以下查询是否符合您的要求。 可能对您有所帮助,此查询基于SQL Server 2012+。 ID = 9正在由我添加。

CREATE TABLE #ti(F_In_Out_Date DATETIME,INQTY FLOAT ,F_lot_number VARCHAR(100),BOE VARCHAR(100))
INSERT INTO #ti
SELECT '2016-05-31',80,'1606427A161','14-2-4-15451983' UNION ALL
SELECT '2016-05-31',15,'1606427A161','14-2-4-15451983' UNION ALL
SELECT '2016-05-31',5,'1606427A161','14-2-4-15451983' UNION ALL
SELECT '2016-08-02',60,'1606427A161','14-2-4-15546475' UNION ALL
SELECT '2016-08-02',10,'1606427A161','14-2-4-15546475' 
--DROP TABLE #to
CREATE TABLE #to(ID INT ,F_In_Out_Date DATETIME,OUTTY FLOAT ,F_lot_number VARCHAR(100),BOE VARCHAR(100))
INSERT INTO #to
SELECT 1,'2016-08-14',5,'1606427A161',NULL UNION ALL
SELECT 2,'2016-08-14',5,'1606427A161',NULL UNION ALL
SELECT 3,'2016-08-14',5,'1606427A161',NULL UNION ALL
SELECT 4,'2016-08-18',5,'1606427A161',NULL UNION ALL
SELECT 5,'2016-08-18',5,'1606427A161',NULL UNION ALL
SELECT 6,'2016-08-18',5,'1606427A161',NULL UNION ALL
SELECT 7,'2016-08-18',5,'1606427A161',NULL UNION ALL
SELECT 8,'2016-08-18',5,'1606427A161',NULL  UNION ALL
SELECT 9,'2016-08-12',100,'1606427A161',NULL 
UPDATE t SET t.BOE=x.BOE
--SELECT t.*,x.*,o.CurrentOutQty
FROM #to AS t
INNER JOIN (
   SELECT *, SUM(OUTTY)OVER(PARTITION BY F_lot_number ORDER BY F_In_Out_Date desc) AS CurrentOutQty 
   FROM #to AS oo
) AS o ON o.ID=t.ID
CROSS APPLY (
   SELECT TOP 1 i.BOE,i.CurrentInQty 
   FROM (
      SELECT *,SUM(INQTY)OVER( PARTITION BY F_lot_number ORDER BY F_In_Out_Date desc) AS CurrentInQty
      FROM #ti AS ii WHERE ii.F_lot_number=o.F_lot_number 
   ) AS i WHERE i.CurrentInQty>=o.CurrentOutQty ORDER BY i.CurrentInQty
) AS x

SELECT * FROM #to
ID          F_In_Out_Date           OUTTY                  F_lot_number         BOE
----------- ----------------------- ---------------------- -------------------- --------------------
1           2016-08-14 00:00:00.000 5                      1606427A161          1606427A161
2           2016-08-14 00:00:00.000 5                      1606427A161          1606427A161
3           2016-08-14 00:00:00.000 5                      1606427A161          1606427A161
4           2016-08-18 00:00:00.000 5                      1606427A161          1606427A161
5           2016-08-18 00:00:00.000 5                      1606427A161          1606427A161
6           2016-08-18 00:00:00.000 5                      1606427A161          1606427A161
7           2016-08-18 00:00:00.000 5                      1606427A161          1606427A161
8           2016-08-18 00:00:00.000 5                      1606427A161          1606427A161
9           2016-08-12 00:00:00.000 100                    1606427A161          1606427A161