I have written the following SQL query which gives the result not in a way I desire. The only change I want is that, I don’t want to repeat the subtotal on every single line, which is what my query is doing now:
Instead, I want it only on the last row of every unique bill_number:
The query is
SELECT
ROW_NUMBER() OVER(
ORDER BY
S.bill_num
) SN,
ROW_NUMBER() OVER(
PARTITION BY S.bill_num
ORDER BY
S.bill_num
) AS [ITEM_NO.],
s.bill_date AS [BILL_DATE],
s.bill_num AS [BILL_NO.],
s.custid AS [CUST_ID],
c.fullname [CUSTOMER],
s.article AS [ARTICLE],
s.price AS [MRP],
s.linetotal AS [TOTAL],
b.billamt as [BILL_TOTAL]
FROM
sold s
LEFT JOIN customers c ON s.custid = c.custid
LEFT JOIN bills b ON S.bill_num = B.bill_num
WHERE
s.bill_date = CONVERT(date, '2020/12/01') AND B.isexpress <> 'P'
ORDER by
S.bill_num
I guess you get the idea of what I want from the images given
Advertisement
Answer
You can do this with row_number()
and a CASE
expression.
However, your query and result suggest that you have multiple rows sharing the same s.bill_num
; to get a stable result, you need a column that can be used to unambigously order rows having duplicate values – let me assume s.id
:
SELECT
ROW_NUMBER() OVER(ORDER BY S.bill_num, S.id) SN,
ROW_NUMBER() OVER(PARTITION BY S.bill_num ORDER BY S.id) AS [ITEM_NO.],
s.bill_date AS [BILL_DATE],
s.bill_num AS [BILL_NO.],
s.custid AS [CUST_ID],
c.fullname [CUSTOMER],
s.article AS [ARTICLE],
s.price AS [MRP],
s.linetotal AS [TOTAL],
CASE WHEN ROW_NUMBER() OVER(PARTITION BY S.bill_num ORDER BY S.id DESC) = 1 THEN b.billamt END as [BILL_TOTAL]
FROM sold s
LEFT JOIN customers c ON s.custid = c.custid
LEFT JOIN bills b ON S.bill_num = B.bill_num AND B.isexpress <> 'P'
WHERE s.bill_date = CONVERT(date, '2020/12/01')
ORDER by S.bill_num
Note that I moved the condition on B.isexpress
from the WHERE
clause to the ON
clause of the relevant LEFT JOIN
; otherwise, this would filter out rows that have no match in bills
– which does not seem to be your intent.