SQL Server How to offset 1 record in SQL?

hl0ma9xz  于 2023-10-15  发布在  其他
关注(0)|答案(2)|浏览(133)

I have this record in my SQL Server database, I can't find a way to offset a record or get this expected result:
| transDate | transTime | termId | transNumber | barcode | itemDescription | price | quantity | netTotal | transType |
| ------------ | ------------ | ------------ | ------------ | ------------ | ------------ | ------------ | ------------ | ------------ | ------------ |
| 2023-10-03 | 03:26PM | 1 | 2496 | 4801010504207 | JBabyOilAloe&VitE50m | 52.25 | 1 | 52.25 | Standard Sale |
| 2023-10-03 | 03:26PM | 1 | 2496 | 4801010504207 | JBabyOilAloe&VitE50m | 52.25 | 1 | 52.25 | Standard Sale |
| 2023-10-03 | 03:26PM | 1 | 2496 | 4809011681439 | BoyBawanhiccorn100g | 25.25 | 1 | 25.25 | Standard Sale |

This is the current content of the table:

transDatetransTimetermIdtransNumberbarcodeitemDescriptionpricequantitynetTotaltransType
2023-10-0303:26PM124964801010504207JBabyOilAloe&VitE50m52.25152.25Standard Sale
2023-10-0303:26PM124964801010504207JBabyOilAloe&VitE50m52.25152.25Standard Sale
2023-10-0303:26PM124964801010504207JBabyOilAloe&VitE50m52.25152.25Standard Sale
2023-10-0303:26PM124964809011681439BoyBawanhiccorn100g25.25125.25Standard Sale
2023-10-0303:27PM124964801010504207JBabyOilAloe&VitE50m52.25-1-52.25Item Voided

In my current table: The requirement is to get the detailed sales, where Item Voided is not included, and there's no identifier to identify which record was the link where a record has transType = Item Voided. It is a raw data inserted and the owner only wants to get the Standard Sale but there will be a discrepancy since 1 record should be offset by Item Voided. This can be fixed easily by SUM and GROUP BY but the problem is the owner wants to see the detailed lines of transaction.

I'm out of idea's on how to achieve what he wants. Can anybody please help me?

I've tried this, but it did not work or displayed the expected result that I wanted:

WITH SaleCounts AS (
    SELECT
        *,
        CASE
            WHEN transType= 'Item Voided' THEN 1
            ELSE ROW_NUMBER() OVER (PARTITION BY barcode, itemDescription, quantity ORDER BY (SELECT NULL))
        END AS RowNum
    FROM
        sales_details 
)

SELECT transDate, transTime, termId, transNumber, barcode, itemDescription, price, quantity, netTotal, transType
FROM
    SaleCounts
WHERE
    RowNum > 1
    OR transType<> 'Item Voided' and transNumber='2496'
ORDER by transDate, transTime, termId, transNumber;

Result:

transDatetransTimetermIdtransNumberbarcodeitemDescriptionpricequantitynetTotaltransType
2023-10-0303:26PM124964809011681439BoyBawanhiccorn100g25.25125.25Standard Sale
2023-10-0303:26PM124964801010504207JBabyOilAloe&VitE50m52.25152.25Standard Sale
2023-10-0303:26PM124964801010504207JBabyOilAloe&VitE50m52.25152.25Standard Sale
2023-10-0303:26PM124964801010504207JBabyOilAloe&VitE50m52.25152.25Standard Sale

I've also tried to present this result but he did not want this:

SELECT 
    transDate, transTime, termId, transNumber, barcode, 
    itemDescription, price, 
    SUM(CAST(quantity AS float)) quantity, 
    SUM(CAST(netTotal AS float)) netTotal, transType
FROM 
    sales_details
WHERE 
    transNumber = '2496'
GROUP BY 
    transDate, transTime, termId, transNumber, barcode, 
    itemDescription, price, quantity, netTotal, transType;

Result:

transDatetransTimetermIdtransNumberbarcodeitemDescriptionpricequantitynetTotaltransType
2023-10-03124964801010504207JBabyOilAloe&VitE50m52.252104.5
2023-10-03124964809011681439BoyBawanhiccorn100g25.25125.25
cigdeys3

cigdeys31#

WITH
  A AS (
      SELECT
        *,
        ROW_NUMBER() OVER(PARTITION BY transDate, 
                                       transTime, 
                                       termId, 
                                       transNumber,  
                                       barcode, 
                                       itemDescription, 
                                       ABS(price),
                                       transType 
                          ORDER BY transDate) AS row_num
      FROM
          table1 ),

  B AS (
      SELECT
        *,
        COUNT(*) OVER(PARTITION BY transDate, 
                                   termId, 
                                   transNumber, 
                                   barcode, 
                                   itemDescription, 
                                   ABS(price),
                                   row_num
                      ORDER BY transDate) AS count1
      FROM
        A)

SELECT
    transDate,
    transTime,
    termId,
    transNumber,
    barcode,
    itemDescription,
    price,
    quantity,
    netTotal,
    transType
FROM
   B
WHERE
  count1 <2

Result:

transDatetransTimetermIdtransNumberbarcodeitemDescriptionpricequantitynetTotaltransType
2023-10-0303:26PM124964801010504207JBabyOilAloe&VitE50m52.25152.25Standard Sale
2023-10-0303:26PM124964801010504207JBabyOilAloe&VitE50m52.25152.25Standard Sale
2023-10-0303:26PM124964809011681439BoyBawanhiccorn100g25.25125.25Standard Sale
kq4fsx7k

kq4fsx7k2#

Perform a matching between active transaction ( quantity > 0 ) with void transaction ( quantity < 0 ) based on transNumber , barcode , price , quantity (negate of the void transaction). And ignore those with matches ( v.transNumber is null )

This is on the assumption that the void transaction should have the same barcode & price value but with quantity value negative.

The matching is also based on price , because there might be situation that same barcode & quantity but at different price

select a.*
from   (   
           select *,
                  rn = row_number() over (partition by transNumber, barcode, price, quantity
                                              order by transtime)
           from   sales_details
           where  quantity > 0 -- Active
       ) a
       left join
       (   
           select *,
                  rn = row_number() over (partition by transNumber, barcode, price, quantity
                                              order by transtime)
           from   sales_details
           where  quantity < 0  -- Void 
       ) v on  a.transNumber = v.transNumber
           and a.barcode     = v.barcode
           and a.price       = v.price
           and a.quantity    = -v.quantity
           and a.rn          = v.rn
where v.transNumber is null

db<>fiddle demo

Side Note: Don't cast the quantity or NetTotal to float ( CAST(quantity AS float) ). Floating point value are approximate value. You should be storing quantity in numeric data type like integer or decimal or numeric

相关问题