根据数量将行拆分为多行

Split rows into multiple rows based on quantity

我的 table 中有一行:

 id  m_id quantity
 1   1  1500
 2   1  -1000
 3   2  -3000
 4   2   2000
 5   3  400
 6   3  -1000
 7   4   500
 8   4   -500
 9   5   1500

我想创建一个视图 return 这个:

 id   m_id   quantity
  1  1    500
  2  1    1000
  3   1    -1000
  4   2   -1000
  5   2   -2000
  6   2   2000
  7   3   400
  8   3   -400
  9   3   -600
  10  4   500
  11  4   -500
  12  5   1500

View 将 return 等于 positive/negative 中的值,并将其余值拆分为单独的行。因此,如果给定 m_id.

的正数和负数不同,则将两行分成三行

我想你可以使用这样的查询:

WITH t1 AS (
    SELECT *, 
        LAG(quantity) OVER (PARTITION BY m_id ORDER BY id) as pq, -- Previous quantity based on id
        LEAD(quantity) OVER (PARTITION BY m_id ORDER BY id) as nq -- Next quantity based on id
    FROM yourTable    
), t2 AS (
SELECT id, m_id, 1 as ord,
    CASE 
        -- If sign is changed and quantity is bigger than that use next quantity
        WHEN (SIGN(nq) <> SIGN(quantity)) AND (ABS(quantity) > ABS(nq)) THEN -nq
        -- If sign is changed and quantity is bigger than that use previous quantity
        WHEN (SIGN(pq) <> SIGN(quantity)) AND (ABS(quantity) > ABS(pq)) THEN -pq
        -- Else use original quantity
        ELSE quantity
    END As quantity
FROM t1
UNION ALL  -- Add extra rows
SELECT id , m_id,
    CASE 
        -- Set order to be higher than original quantity
        WHEN (SIGN(nq) <> SIGN(quantity)) AND (ABS(quantity) > ABS(nq)) THEN 0
        -- Set order to be lower than original quantity
        WHEN (SIGN(pq) <> SIGN(quantity)) AND (ABS(quantity) > ABS(pq)) THEN 2
    END As ord,
    -- quantity is difference
    CASE 
        WHEN (SIGN(nq) <> SIGN(quantity)) AND (ABS(quantity) > ABS(nq)) THEN nq + quantity
        WHEN (SIGN(pq) <> SIGN(quantity)) AND (ABS(quantity) > ABS(pq)) THEN pq + quantity
    END As quantity
FROM t1
WHERE   
    -- Find differences more
    1 = CASE 
            WHEN (SIGN(nq) <> SIGN(quantity)) AND (ABS(quantity) > ABS(nq)) THEN 1
            WHEN (SIGN(pq) <> SIGN(quantity)) AND (ABS(quantity) > ABS(pq)) THEN 1
            ELSE 0
        END)
SELECT 
    -- Use new values for id
    ROW_NUMBER() OVER (ORDER BY id, ord) As id, 
    m_id, quantity
FROM t2;