How to remove duplicate entries in my query? - sql

The following code gives me multiple lines since there can be more than one Cust_Edit_Log.Edit_Timestamp per Alarm Account. There is no other way for a duplicate to occur. How do I only get the result with the earliest Cust_Edit_Log.Edit_Timestamp date? Thank you in advance for any help you can provide.
Select
AR_Customer.Customer_Number As 'Customer_Number',
AR_Customer.Customer_Name As 'Customer_Name',
AR_Customer_System.Alarm_Account As 'Alarm_Account',
AR_Customer_Site.Address_1 As 'Site_Address_1',
Cust_Edit_Log.UserComments As 'Edit_Log_Cust_User_Comments',
Cust_Edit_Log.Edit_Timestamp As 'Edit_Log_Cust_Timestamp',
Cust_Edit_Log.UserCode As 'Edit_Log_Cust_User'
From
AR_Customer
Inner JOIN AR_Customer_Site On AR_Customer.Customer_Id = AR_Customer_Site.Customer_Id
Left Outer JOIN AR_Customer_System On AR_Customer_Site.Customer_Site_Id = AR_Customer_System.Customer_Site_Id
Left Outer Join CQB_Log_Parse Cust_Edit_Log on AR_Customer.Customer_Id = Cust_Edit_Log.Customer_Id
Where
AR_Customer.Customer_Id <> 1 And
(AR_Customer_System.Alarm_Account Like 'IN%' And
Cust_Edit_Log.UserComments Like 'Edited Customer System IN%')
Order By
AR_Customer.Customer_Number ASC

Use Partition BY:
SELECT
X.*
FROM
(
Select
AR_Customer.Customer_Number As 'Customer_Number',
AR_Customer.Customer_Name As 'Customer_Name',
AR_Customer_System.Alarm_Account As 'Alarm_Account',
AR_Customer_Site.Address_1 As 'Site_Address_1',
Cust_Edit_Log.UserComments As 'Edit_Log_Cust_User_Comments',
Cust_Edit_Log.Edit_Timestamp As 'Edit_Log_Cust_Timestamp',
Cust_Edit_Log.UserCode As 'Edit_Log_Cust_User',
ROW_NUMBER() OVER(Partition BY AR_Customer_System.Alarm_Account,Cust_Edit_Log.Edit_Timestamp ORDER BY AR_Customer_System.Alarm_Account) AS PartNO
From
AR_Customer
Inner JOIN AR_Customer_Site On AR_Customer.Customer_Id = AR_Customer_Site.Customer_Id
Left Outer JOIN AR_Customer_System On AR_Customer_Site.Customer_Site_Id = AR_Customer_System.Customer_Site_Id
Left Outer Join CQB_Log_Parse Cust_Edit_Log on AR_Customer.Customer_Id = Cust_Edit_Log.Customer_Id
Where
AR_Customer.Customer_Id <> 1 And
(AR_Customer_System.Alarm_Account Like 'IN%' And
Cust_Edit_Log.UserComments Like 'Edited Customer System IN%')
)X
WHERE X.PartNo=1
Order By X.Customer_Number ASC

One method uses row_number():
Left Outer Join
(select lp.*,
row_number() over (partition by lp.Customer_Id
order by Edit_Timestamp asc
) as seqnum
from CQB_Log_Parse lp
) Cust_Edit_Log
on AR_Customer.Customer_Id = Cust_Edit_Log.Customer_Id and
seqnum = 1

Maybe try with MIN(Cust_Edit_Log.Edit_Timestamp)

You can try using as below:
;with cte as (
Select
AR_Customer.Customer_Number As 'Customer_Number',
AR_Customer.Customer_Name As 'Customer_Name',
AR_Customer_System.Alarm_Account As 'Alarm_Account',
AR_Customer_Site.Address_1 As 'Site_Address_1',
Cust_Edit_Log.UserComments As 'Edit_Log_Cust_User_Comments',
Cust_Edit_Log.Edit_Timestamp As 'Edit_Log_Cust_Timestamp',
Cust_Edit_Log.UserCode As 'Edit_Log_Cust_User'
,row_number() over(partition by AR_Customer.Customer_Number order by Cust_Edit_Log.Edit_Timestamp) as rownum
From
AR_Customer
Inner JOIN AR_Customer_Site On AR_Customer.Customer_Id = AR_Customer_Site.Customer_Id
Left Outer JOIN AR_Customer_System On AR_Customer_Site.Customer_Site_Id = AR_Customer_System.Customer_Site_Id
Left Outer Join CQB_Log_Parse Cust_Edit_Log on AR_Customer.Customer_Id = Cust_Edit_Log.Customer_Id
Where
AR_Customer.Customer_Id <> 1 And
(AR_Customer_System.Alarm_Account Like 'IN%' And
Cust_Edit_Log.UserComments Like 'Edited Customer System IN%')
--Order By
--AR_Customer.Customer_Number ASC
)
select * from cte where rownum = 1
order by AR_Customer.Customer_Number ASC

Related

Join with max improve query

select Tf.*
from SalesOrder SO
join TransportOrder Tf on Tf.SalesOrderID = SO.SalesOrderID
join (
select Sz.TradingPartner, Sz.ExternalSalesOrder, Tz.TransportOrderNumber, max(Tz.Revision) Revision
from SalesOrder Sz
join TransportOrder Tz on Sz.SalesOrderID = Tz.SalesOrderID
group by Sz.TradingPartner, Sz.ExternalSalesOrder, Tz.TransportOrderNumber
) TU on TU.TradingPartner = SO.TradingPartner and TU.ExternalSalesOrder = SO.ExternalSalesOrder and TU.TransportOrderNumber = Tf.TransportOrderNumber and Tf.Revision = TU.Revision
I want to know If I can improve it?
What I want to do:
select the TransportOrders that have the maximum revision.
a transport order can be identified with salesOrder.TradingPartner, salesOrder.ExternalSalerOrder, transportOrder.TransportOrderNumer and transportOrder.Revision (used as a version field)
so I want all the transportorder with last version
You can use the ROW_NUMBER analytical function as follows:
SELECT * FROM
(SELECT TF.*,
ROW_NUMBER()
OVER (PARTITION BY SZ.TRADINGPARTNER,
SZ.EXTERNALSALESORDER,
TZ.TRANSPORTORDERNUMBER
ORDER BY TZ.REVISION DESC) AS RN
FROM SALESORDER SO
JOIN TRANSPORTORDER TF
ON TF.SALESORDERID = SO.SALESORDERID
JOIN SALESORDER SZ
ON SZ.TRADINGPARTNER = SO.TRADINGPARTNER
AND SZ.EXTERNALSALESORDER = SO.EXTERNALSALESORDER
JOIN TRANSPORTORDER TZ
ON SZ.SALESORDERID = TZ.SALESORDERID
AND TRANSPORTORDERNUMBER = TF.TRANSPORTORDERNUMBER
)
WHERE TF.REVISION = TU.REVISION
I would suggest window functions
select st.*
from (select t.*, so.TradingPartner, so.ExternalSalerOrder,
max(t.revision) over (partition by so.TradingPartner, so.ExternalSalerOrder, t.TransportOrderNumber) as max_revision
from SalesOrder SO join
TransportOrder t
on t.SalesOrderID = so.SalesOrderID
) st
where revision = max_revision;
No need to reopen the two tables. You can use window functions like this:
select *
from (
select t.*,
rank() over(
partition by s.TradingPartner, s.ExternalSalerOrder, t.TransportOrderNumer
order by t.Revision desc
) rn
from SalesOrder s
join TransportOrder t on t.SalesOrderID = s.SalesOrderID
) t
where rn = 1

Select all records between two dates but one record on same day depending on plate

I have select query :
select
f.FirmaID,f.FirmaAdi,t.BelgeID,t.BelgeTuru,t.Tarih,t2.Plaka,t2.SasiNo,t4.AracMarka,t4.AracTip,case when x.Miktar=1 then 4 else x.miktar end as LastikAdet,
t3.CariKodu,t3.CariAdi,t3.CariGsm1,t3.CariGsm2,t3.CariTel1,t3.CariTel2,t3.CariAdres
from alsatr t WITH (NOLOCK)
left join Firma f WITH (NOLOCK) on f.FirmaID = t.AlsatrFirmaID
left join AracBilgi t2 WITH (NOLOCK) on t2.AracBilgiUID = t.AsAracBilgiUID and t2.AracBilgiID= t.AracBilgi
left join Cari t3 WITH (NOLOCK) on t.AsCariUID= t3.CariUID
left join Araclar t4 WITH (NOLOCK) on t4.AracID= t2.AB_AracID
outer apply
(select COUNT(1) soktak,Miktar FROM alsatD d WITH (NOLOCK)
where
d.AlsatDUID = t.AlsatrUID and d.AsStokKodu='LA-0001' group by Miktar) x
where
isnull(t3.FiloID,0) > 0
and t.Tarih between '04.30.2020' and '04.31.2020'
and t.BelgeTuru=55
and x.soktak > 0
and f.FirmaID not in (1,2,103,106,109,114)
order by t.Tarih desc, f.FirmaID desc, t.BelgeID desc
So I want to select all records between two days but I want to select one,latest record (maybe depends on last BelgeID ) on same day with same plate (plaka).
Enclose your query inside a CTE and use ROW_NUMBER() window function:
WITH cte AS (
<your query here>
)
SELECT
t.FirmaID, t.FirmaAdi, t.BelgeID, t.BelgeTuru, t.Tarih, t.Plaka, t.SasiNo, t.AracMarka,
t.AracTip, t.LastikAdet, t.CariKodu, t.CariAdi, t.CariGsm1, t.CariGsm2, t.CariTel1,
t.CariTel2, t.CariAdres
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY Tarih, Plaka ORDER BY BelgeID DESC) rn
FROM cte
) t
WHERE t.rn = 1

Join two tables returning only one row from the second table

I have this query:
SELECT t_ticket.ticketID, t_ticket.addedDate, t_ticket.question,
t_ticket.code, t_ticket.priority, t_actionTicket.addedDateAction, t_actionTicket.title
FROM t_actionTicket INNER JOIN
t_ticket ON t_actionTicket.ticketID_FK = t_ticket.ticketID INNER JOIN
(SELECT ticketID_FK, MAX(addedDateAction) AS maxDate
FROM t_actionTicket AS t_actionTicket_1
WHERE (t_actionTicket.userID_FK <> #userid)
GROUP BY ticketID_FK) AS b ON t_actionTicket.ticketID_FK = b.ticketID_FK AND t_actionTicket.addedDateAction = b.maxDate
WHERE (t_ticket.supporterID_FK IN
(SELECT supporterID
FROM t_Supporter
WHERE (userID_FK = #userid)))
I want to return just the latest record in t_actionTicket table for each row in t_ticket table that t_actionTicket.userID_FK <> #userid.
but I have this error:
The multi-part identifier "t_actionTicket.userID_FK" could not be
bound.
Problem in your query is
FROM t_actionTicket AS t_actionTicket_1
WHERE t_actionTicket.userID_FK <> #userid -- here
You cannot use t_actionTicket alias name inside inner join select query. You need to use t_actionTicket_1. It is possible only in sub-query
Try this better way of doing it
;WITH cte
AS (SELECT t_ticket.ticketID,
t_ticket.addedDate,
t_ticket.question,
t_ticket.code,
t_ticket.priority,
t_actionTicket.addedDateAction,
t_actionTicket.title,
Row_number()
OVER(
partition BY ticketID_FK
ORDER BY addedDateAction DESC) RN
FROM t_actionTicket
INNER JOIN t_ticket
ON t_actionTicket.ticketID_FK = t_ticket.ticketID
WHERE t_ticket.supporterID_FK IN (SELECT supporterID
FROM t_Supporter
WHERE userID_FK = #userid))
SELECT *
FROM cte
WHERE rn = 1
You can write this logic using row_number() instead of additional nested queries:
SELECT t.ticketID, t.addedDate, t.question, t.code, t.priority,
ta.addedDateAction, ta.title AS Expr1
FROM t_Ticket t INNER JOIN
(SELECT ta.*,
ROW_NUMBER() OVER (PARTITION BY ta.ticketID_FK ORDER BY ta.addedDateAction DESC) as seqnum
FROM t_actionTicket ta
) ta
ON t.ticketId = ta.ticketId_FK and ta.seqnum = 1
WHERE t.supporterID_FK IN (SELECT supporterID
FROM t_Supporter
WHERE userID_FK = #userid
);
Note that table aliases make the query easier to write and to read.
Try this query
SELECT t_ticket.ticketID, t_ticket.addedDate, t_ticket.question,
t_ticket.code, t_ticket.priority, t_actionTicket.addedDateAction, t_actionTicket.title
FROM t_actionTicket
INNER JOIN t_ticket ON t_actionTicket.ticketID_FK = t_ticket.ticketID
INNER JOIN (SELECT ticketID_FK, MAX(addedDateAction) AS maxDate
FROM t_actionTicket AS t_actionTicket_1
WHERE (t_actionTicket_1.userID_FK <> #userid)
GROUP BY ticketID_FK) AS b ON t_actionTicket.ticketID_FK = b.ticketID_FK AND t_actionTicket.addedDateAction = b.maxDate
WHERE (t_ticket.supporterID_FK IN
(SELECT supporterID
FROM t_Supporter
WHERE (userID_FK = #userid)))

Limiting result sets by future date - SQL

The Query below produces a record for each Entry in the SP_ScheduleEvent Table.
SELECT m.MaterialId, m.MaterialTitle, se.EventDateTime, c.ChannelName
FROM GB_Material m
LEFT OUTER JOIN SP_ScheduleEvent se on se.MaterialName = m.MaterialName
INNER JOIN SP_Schedule s on s.ScheduleID = se.ScheduleID
INNER JOIN GB_Channel c on c.ChannelID = s.ChannelID
WHERE LOWER(m.MaterialName) like '%foo%' OR LOWER(m.MaterialTitle) like '%foo%'
I want to limit the result set by the nearest future EventDateTime.
So per material name i would like to see one EventDateTime, which should be the nearest future date to the current time.
And lastly, a record may not exist in the SP_ScheduleEvent table for a particular materialname, in which case there should be null returned for the EventDateTime column
SQLFiddle
How would i go about doing this?
First, your LEFT JOIN is immaterial, because the subsequent joins make it an INNER JOIN. Either use LEFT JOIN throughout the FROM statement or switch to INNER JOIN.
I think you can use ROW_NUMBER():
SELECT t.*
FROM (SELECT m.MaterialId, m.MaterialName, m.MaterialTitle, se.EventDateTime,
ROW_NUMBER() over (PARTITION BY m.MaterialId OVER se.EventDateTime DESC) as seqnum
FROM GB_Material m INNER JOIN
SP_ScheduleEvent se
on se.MaterialName = m.MaterialName INNER JOIN
SP_Schedule s
on s.ScheduleID = se.ScheduleID INNER JOIN
GB_Channel c
on c.ChannelID = s.ChannelID
WHERE se.EventDateTime > getdate() AND
(LOWER(m.MaterialName) like '%foo%' OR LOWER(m.MaterialTitle) like '%foo%')
) t
WHERE seqnum = 1
ORDER BY se.EventDateTime;
Use the ROW_NUMBER() function:
WITH cte AS (
SELECT m.MaterialId, m.MaterialTitle, se.EventDateTime, c.ChannelName,
ROW_NUMBER() OVER (PARTITION BY m.MaterialId ORDER BY EventDateTime ASC) AS rn
FROM GB_Material m
LEFT OUTER JOIN SP_ScheduleEvent se on se.MaterialName = m.MaterialName
LEFT OUTER JOIN SP_Schedule s on s.ScheduleID = se.ScheduleID
LEFT OUTER JOIN GB_Channel c on c.ChannelID = s.ChannelID
WHERE LOWER(m.MaterialName) like '%foo%' OR LOWER(m.MaterialTitle) like '%foo%'
AND se.EventDateTime > GETDATE()
)
SELECT * FROM cte
WHERE rn=1

How would that be possible to make this SQL Query simpler/shorter?

It should return some fields from the SystemTable and the LoadStatus column of the latest record in the ProcessHistory table. The relationship is 1 to many:
SELECT ST.[SystemDetailID], ST.[SystemName], LH.LatestLoadStatus
FROM [SystemTable] AS ST
LEFT OUTER JOIN
(
SELECT LHInner.LoadStatus AS LatestLoadStatus, LHInner.SystemDetailID FROM [dbo].[LoadHistory] AS LHInner
WHERE LHInner.LoadHistoryID in
(
SELECT LatestLoadHisotoryID FROM
(
SELECT MAX(LoadHistoryID) as LatestLoadHisotoryID, SystemDetailID FROM [dbo].[LoadHistory]
GROUP BY SystemDetailID
) l
)
) AS LH ON ST.SystemDetailID = LH.SystemDetailID
Thanks,
This is a greatest-n-per-group query.
One Approach
SELECT ST.[SystemDetailID],
ST.[SystemName],
LH.LatestLoadStatus
FROM [SystemTable] AS ST
OUTER APPLY (SELECT TOP 1 *
FROM [dbo].[LoadHistory] LH
WHERE ST.SystemDetailID = LH.SystemDetailID
ORDER BY LoadHistoryID DESC) LH
You can also use row_number
WITH LH
AS (SELECT *,
ROW_NUMBER() OVER (PARTITION BY SystemDetailID
ORDER BY LoadHistoryID DESC) RN
FROM [dbo].[LoadHistory])
SELECT ST.[SystemDetailID],
ST.[SystemName],
LH.LatestLoadStatus
FROM [SystemTable] AS ST
LEFT JOIN LH
ON LH.SystemDetailID = ST.SystemDetailID
AND LH.RN = 1
SELECT ST.[SystemDetailID], ST.[SystemName], LH.LatestLoadStatus
FROM [SystemTable] AS ST
INNER JOIN [dbo].[LoadHistory] AS LH
ON ST.SystemDetailID = LH.SystemDetailID
AND LH.LoadHistoryID IN
(SELECT MAX(LoadHistoryID) as LoadHistoryID
FROM [dbo].[LoadHistory]
GROUP BY SystemDetailID )