SQL Server-How to avoid repetition of a column in the output - sql

Output of my SQL Server Query is as below:
Following is my query:
SELECT
si.SupplyInvoiceID,
si.CompanyID,
si.TotalBill,
siph.BillPaidAmount,
si.TotalBill - SUM(siph.BillPaidAmount)
over( partition by si.SupplyInvoiceID order by siph.SupplyPaymentID asc) as RemainingBillAmount
from
SupplyInvoicePaymentHistory siph
left join
SupplyInvoice si
on siph.SupplyInvoiceID = si.SupplyInvoiceID
I want that in output column TotaBill, bill amount should be shown only one for each SupplyInvoiceID i.e
Required Output

Your problem requires an ordering for the table. It appears to be by SupplyPaymentId (although any column can be used). To do what you want, you can use row_number() and an explicit order by in the query:
select si.SupplyInvoiceID, si.CompanyID,
(CASE WHEN ROW_NUMBER() OVER (PARTITION BY si.SupplyInvoiceID order by siph.SupplyPaymentID) = 1
THEN si.TotalBill
END) as TotalBill
siph.BillPaidAmount,
(si.TotalBill -
SUM(siph.BillPaidAmount) over (partition by si.SupplyInvoiceID order by siph.SupplyPaymentID asc)
) as RemainingBillAmount
from SupplyInvoicePaymentHistory siph left join
SupplyInvoice si
on siph.SupplyInvoiceID = si.SupplyInvoiceID
order by si.SupplyInvoiceID, siph.SupplyPaymentID

Related

get las record from group in postgres?

i have the next structure for db, i need to get only the most recent row by id, for example the most recen row for id 1, the most recen row for id 2, etc, for the moment i have this query:
SELECT max(fecha), id_transaccion, id_movimiento
FROM transaccion_movimiento
group by (id_transaccion, id_movimiento, fecha);
To later adapt to this:
LEFT JOIN (SELECT max(fecha), id_transaccion, id_movimiento FROM transaccion_movimiento group by (id_transaccion, id_movimiento, fecha) ORDER BY ID_TRANSACCION asc LIMIT 1)nn ON T.id_transaccion = nn.id_transaccion LEFT JOIN ctl_tipo_movimiento IM ON IM.id_tipo_movimiento = nn.id_movimiento " +
Please i need help
I suggest you consider using row_number() over() instead. See Window Functions
SELECT
*
FROM x
LEFT JOIN (
SELECT
fecha
, id_transaccion
, id_movimiento
, ROW_NUMBER() OVER (PARTITION BY id_transaccion, id_movimiento
ORDER BY fecha DESC) AS ultima_fecha_row
FROM transaccion_movimiento
) nn ON T.id_transaccion = nn.id_transaccion asn nn.ultima_fecha_row=1
LEFT JOIN ctl_tipo_movimiento im ON im.id_tipo_movimiento = nn.id_movimiento
Now whilst I recognized fecha to mean date not much else made sense to me, so you may have to adjust this suggestion. For example I'm not sure if id_movimiento is needed in the "partition" or not.
, ROW_NUMBER() OVER (PARTITION BY id_transaccion
ORDER BY fecha DESC) AS ultima_fecha_row

Trying to retrieve first rows partition by offer_id

Suppose I have a table with columns
body | offer_id | created_at
I need to group them by offer_id, order by created_at and then retrieve first row in this table. I am now using the following logic
select first_value(M.body) over (partition by M.offer_id order by M.created_at ASC ROWS UNBOUNDED PRECEDING),
(select created_at
from quotes_site.offers O
where O.id = M.offer_id) as crt
from quotes_site.messages M
where M.created_at between '2016-01-01' and '2016-02-01'
Although there is no error, the query runs indefinitely so I assume there must be something wrong. I am also not very familiar with the frame clause so more detailed explanation would be greatly appreciated
P.S. Server runs on AWS Redshift
I'll suggest row_number():
SELECT * FROM (
SELECT t.offer_id,t.body,t.created_at,s.created_at,
ROW_NUMBER() OVER(PARTITION BY t.offer_ID ORDER BY t.created_at) as rnk
FROM quotes_site.messages t
INNER JOIN quotes_site.offers s
ON(s.id = t.offer_id))
WHERE rnk = 1
How about using distinct on instead:
select distinct on (M.offer_Id), M.*, o.created_at as o_created_at
from quotes_site.messages M left join
quotes_site.offers O
ON O.id = M.offer_id
where M.created_at between '2016-01-01' and '2016-02-01'
order by M.offer_id, M.created_at;

(SQL Server) using row count to sort the list but dont need list out the row count number

All the column that inside the select sql are needed to list out ,except the row_number(),any solution to eliminate to row_count ?
SELECT *
FROM
(SELECT Station,
ROW_NUMBER() over (
ORDER BY totalseq ASC) AS rownumber1
FROM [SFCKM].[dbo].[T_DB_Subline]
WHERE Track_Point_No = '3d1')a
LEFT JOIN
(SELECT group_no,
trim_line,
MSC,
lot_no,
color,
AON,
format(Commit_time,'MM/dd/yy h:mm:ss tt')AS time,
datediff(DAY,Commit_Time,SYSDATETIME()) AS aging,
ROW_NUMBER() over (
ORDER BY commit_time DESC) AS rownumber
FROM [SFCKM].[dbo].[T_Work_Actual]
WHERE Track_Point_No = '3d1') c ON a.rownumber1 = c.rownumber
ORDER BY a.rownumber1
You could just select the values you are looking for e.g. Station and aging.
select a.Station, c.aging from
(select Station, ROW_NUMBER() over (order by totalseq asc) AS rownumber1
from [SFCKM].[dbo].[T_DB_Subline] where Track_Point_No = '3d1') a
left join
(*,aging,ROW_NUMBER() over (order by commit_time desc) AS rownumber
FROM [SFCKM].[dbo].[T_Work_Actual] where Track_Point_No = '3d1') c
on a.rownumber1 = c.rownumber
order by a.rownumber1
Don't use SELECT *: specify only the columns you need. SELECT * is not best practice, just lazy
There is no way to exclude a column as per my answer SQL exclude a column using SELECT * [except columnA] FROM tableA?

Want result with out using subquery?

SELECT
ROW_NUMBER()over(partition by tblProductTemplateHdr.product_ID
order by tblProductTemplateHdr.product_ID, tblProcessSequence.sl_No) AS rno,
tblProductTemplateHdr.product_ID
,tblProductProcessHdr.process_ID
,tblProcessSequence.sl_No
FROM
Production.tblProcessSequence
INNER JOIN
Production.tblProductProcessHdr ON tblProductProcessHdr.product_Process_ID = tblProcessSequence.product_Process_ID AND tblProductProcessHdr.isQC_Need = 1
INNER JOIN
Production.tblProductTemplateHdr ON tblProductTemplateHdr.product_Temp_ID = tblProductProcessHdr.product_Temp_ID
I want the row with maximum sl_No in each product_Id without using a subquery, this the result obtained by running this query want to apply filtering on same query
You need to a) rewrite your query just a little, and b) I'd recommend using table aliases to make your query more readable.
Try this:
;WITH ProductData AS
(
SELECT
ROW_NUMBER() OVER (PARTITION BY pth.Product_ID
ORDER BY pth.Product_ID, ps.sl_No DESC) AS rno,
tph.product_ID,
tph.process_ID,
ps.sl_No
FROM
Production.tblProcessSequence ps
INNER JOIN
Production.tblProductProcessHdr pph ON tph.product_Process_ID = ps.product_Process_ID
AND pph.isQC_Need = 1
INNER JOIN
Production.tblProductTemplateHdr tph ON tph.product_Temp_ID = pph.product_Temp_ID
)
SELECT *
FROM
ProductData
WHERE
rno = 1
The ROW_NUMBER() function partitions your data by Product_ID and within each partition, it orders the rows by sl_No DESC - so the highest value of sl_No gets the rno = 1 value (all others get higher numbers, in each partition)
You can use another windowed function:
MAX(tblProcessSequence.sl_No) OVER(PARTITION BY tblProductTemplateHdr.product_ID)
ADDENDUM
Just to give the full query in context in case the above was not clear:
SELECT ROW_NUMBER() OVER (PARTITION BY tempHdr.Product_ID ORDER BY Seq.sl_No DESC) AS rno,
tempHdr.product_ID,
procHdr.process_ID,
Seq.sl_No,
MAX(Seq.sl_No) OVER(PARTITION BY tblProductTemplateHdr.Product_ID) AS Max_SL_No
FROM Production.tblProcessSequence Seq
INNER JOIN Production.tblProductProcessHdr procHdr
ON Seq.product_Process_ID = tblProductProcessHdr.product_Process_ID
AND procHdr.isQC_Need = 1
INNER JOIN Production.tblProductTemplateHdr tempHdr
ON tempHdr.product_Temp_ID = procHdr.product_Temp_ID

Invalid column name in SQL Server

I'm trying to add where condition to my select statement but I'm getting invalid column name exception.
SELECT "Ugly OLAP name" as "Value"
FROM OpenQuery( OLAP, 'OLAP Query')
But if I try to add:
WHERE "Value" > 0
you suggested that I have to use the original name and it works fine.
But what if I can't use the original column name as follow
SELECT
ROW_NUMBER() OVER(PARTITION BY P.ProviderID
ORDER BY T.PostedUTC DESC, T.TransactionID DESC) as RN
FROM
Provider p
INNER JOIN
Transaction T
WHERE
RN = 1
How can I access RN at my where ???
You need to use a CTE or a derived table:
SELECT *
FROM ( SELECT ROW_NUMBER() OVER(PARTITION BY P.ProviderID
ORDER BY T.PostedUTC DESC, T.TransactionID DESC) as RN,
[More Columns]
FROM Provider p
INNER JOIN Transaction T
ON SomeCondition) DT
where DT.RN = 1
Or
;WITH CTE AS
(
SELECT ROW_NUMBER() OVER(PARTITION BY P.ProviderID
ORDER BY T.PostedUTC DESC, T.TransactionID DESC) as RN,
[More Columns]
FROM Provider p
INNER JOIN Transaction T
ON SomeCondition
)
SELECT *
FROM CTE
where RN = 1
You could do it this way:
WITH T AS (
SELECT ROW_NUMBER() OVER(PARTITION BY P.ProviderID ORDER BY T.PostedUTC DESC, T.TransactionID DESC) as RN
From Provider p Inner join Transaction T
)
SELECT RN
FROM T
WHERE RN > 0;
EDIT: Missed second query in the question...
you must repeat the original calculation
Another way to make this easier to understand is to rewrite your query as a series of CTE's - Common Table Expressions. They look and act like 'mini local views' where you can rename columns, etc. It's tough from the example you gave but often you can rewrite complex queries and return to columns with nicer names in subsequent queries.