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

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

Related

I need to only select the minimum value of my query

I have a view created in SQL Server Management Studio that brings in certain data, I need to only select the rows with the minimum sequence. For example, in the screenshot see the job number "50773-4", I would only need to see the row with SEQ number 2. I've tried to Group by Min, but to no avail. Any help would be appreciated.
SELECT
TOP (100) PERCENT dbo.Job_Operation.Job,
MIN(dbo.Job_Operation.Sequence) AS SEQ,
dbo.Job_Operation.Work_Center,
dbo.Work_Center.Department
FROM
dbo.Job_Operation
INNER JOIN dbo.Job ON dbo.Job_Operation.Job = dbo.Job.Job
INNER JOIN dbo.User_Values ON dbo.Job.User_Values = dbo.User_Values.User_Values
INNER JOIN dbo.Work_Center ON dbo.Job_Operation.Work_Center = dbo.Work_Center.Work_Center
GROUP BY
dbo.Job_Operation.Job,
dbo.User_Values.Numeric2,
dbo.Work_Center.UVText4,
dbo.Job.Status,
dbo.Job_Operation.Status,
dbo.User_Values.Decimal1,
dbo.Job_Operation.Work_Center,
dbo.Work_Center.Department
HAVING
(dbo.Work_Center.UVText4 = 'Machining')
ORDER BY
dbo.User_Values.Decimal1 DESC,
SEQ
[enter image description here]
I would try the RANK() window function. Perhaps:
SELECT column1,
column2,
rank() OVER (PARTITION BY job ORDER BY seq) AS seq_by_job
Then use this as a nested statement, and filter on only the min rank (i.e. WHERE nested_statement.seq_by_job = 1)
here is one way :
SELECT
TOP (100) PERCENT Job,
Sequence AS SEQ,
Work_Center,
Department
FROM
( select dbo.Job_Operation.Job,
dbo.Job_Operation.Sequence,
dbo.Job_Operation.Work_Center,
dbo.Work_Center.Department,
dbo.User_Values.Decimal1 ,
ROW_NUMBER() over (partition by dbo.Job_Operation.Job,
dbo.User_Values.Numeric2,
dbo.Work_Center.UVText4,
dbo.Job.Status,
dbo.Job_Operation.Status,
dbo.User_Values.Decimal1,
dbo.Job_Operation.Work_Center,
dbo.Work_Center.Department
Order by dbo.Job_Operation.Sequence asc) rn
FROM
dbo.Job_Operation
INNER JOIN dbo.Job ON dbo.Job_Operation.Job = dbo.Job.Job
INNER JOIN dbo.User_Values ON dbo.Job.User_Values = dbo.User_Values.User_Values
INNER JOIN dbo.Work_Center ON dbo.Job_Operation.Work_Center = dbo.Work_Center.Work_Center
) tt
WHERE rn = 1
and UVText4 = 'Machining'
You can do:
with
q as (
SELECT
dbo.Job_Operation.Job,
MIN(dbo.Job_Operation.Sequence) AS SEQ,
dbo.Job_Operation.Work_Center,
dbo.Work_Center.Department,
dbo.User_Values.Decimal1
FROM
dbo.Job_Operation
INNER JOIN dbo.Job ON dbo.Job_Operation.Job = dbo.Job.Job
INNER JOIN dbo.User_Values
ON dbo.Job.User_Values = dbo.User_Values.User_Values
INNER JOIN dbo.Work_Center
ON dbo.Job_Operation.Work_Center = dbo.Work_Center.Work_Center
GROUP BY
dbo.Job_Operation.Job,
dbo.User_Values.Numeric2,
dbo.Work_Center.UVText4,
dbo.Job.Status,
dbo.Job_Operation.Status,
dbo.User_Values.Decimal1,
dbo.Job_Operation.Work_Center,
dbo.Work_Center.Department
HAVING
(dbo.Work_Center.UVText4 = 'Machining')
),
r as (
select *,
row_number() over(partition by job order by seq) as rn
from q
)
select job, seq, work_center, department
from r
where rn = 1
order by Decimal1 DESC

Count with row_number function SQL CTE

I have the below CTEs that work perfectly, but I want to count the "cl.memb_dim_id" by "cl.post_date" but I am not sure how to do that? When adding in the count function I get an error that highlights the ' row number' so I am assuming I cant have both order and group together ????
WITH
DATES AS
(
select to_date('01-jan-2017') as startdate,to_date('02-jan-2017') as enddate
from dual
),
Claims as (select distinct
cl.memb_dim_id,
row_number () over (partition by cl.Claim_number order by cl.post_date desc) as uniquerow,
cl.Claim_number,
cl.post_date,
ct.claim_type,
ap.claim_status_desc,
dc.company_desc,
dff.io_flag_desc,
pr.product_desc,
cl.prov_dim_id,
cl.prov_type_dim_id
from dw.fact_claim cl
inner join dates d
on 1=1
and cl.post_date >= d.startdate
and cl.post_date <= d.enddate
and cl.provider_par_dim_id in ('2')
and cl.processing_status_dim_id = '1'
and cl.company_dim_id in ('581','585','586','589','590','591','588','592','594','601','602','603','606','596','598','597','579','599','578','577','573','574','576','575')
left join dw.DIM_CLAIM_STATUS ap
on cl.claim_status_dim_id = ap.claim_status_dim_id
left join dw.dim_claim_type ct
on cl.claim_type_dim_id = ct.claim_type_dim_id
and cl.claim_type_dim_id in ('1','2','6','7')
left join dw.DIM_COMPANY dc
on cl.company_dim_id = dc.company_dim_id
left join dw.DIM_IO_FLAG dff
on cl.io_flag_dim_id = dff.io_flag_dim_id
left join dw.dim_product pr
on cl.product_dim_id = pr.product_dim_id
)
Select * from claims where uniquerow ='1'
First, does this work?
count(cl.memb_dim_id) over (partition by cl.Claim_number, cl.post_date) as cnt,
Second, it is strange to be using analytic functions with select distinct.

SQL Server Delete Rows from Table leaving the record with the Max CreationDate

I want to delete the older records from the table based on creation date,leaving the latest one
attempted SQL,but did not work.
SELECT *
--DELETE L
FROM ItemPriceListMap L
LEFT JOIN (
SELECT ItemPriceListUID3,MAX(CAST(CreationDate as DATE)) MaxDate
FROM ItemPriceListMap
GROUP BY ItemPriceListUID3
)M ON L.ItemPriceListUID3 = M.ItemPriceListUID3 AND CAST(L.CreationDate as DATE) = M.MaxDate
WHERE M.ItemPriceListUID3 IS NULL
The view of the mapping
SELECT I.Description,ipl.UnitListPrice1,iplmp.VatMRP,iplmp.CreationDate FROM ItemPriceListMap iplmp
INNER JOIN ItemPriceList ipl ON iplmp.ItemPriceListUID3 = ipl.UID
INNER JOIN Item i ON ipl.ItemUID = i.UID
ORDER BY I.Description,iplmp.CreationDate
EDIT:
More Sample Data
Using this SQL
SELECT I.Description,iplmp.ItemPriceListUID3,iplmp.CreationDate FROM ItemPriceListMap iplmp
INNER JOIN ItemPriceList ipl ON iplmp.ItemPriceListUID3 = ipl.UID
INNER JOIN Item i ON ipl.ItemUID = i.UID
ORDER BY I.Description,iplmp.CreationDate
so after I execute the delete command the highlighted row should be left in the table(yellow),highlighted in blue is the same Item
TRY THIS: You can use your own query by doing some simple changes as below, you have to join as <> with the max date so it will not delete that record, only delete others which matches ItemPriceListUID3 and <> MaxDate
SELECT *
--DELETE L
FROM ItemPriceListMap L
INNER JOIN (SELECT MAX(CAST(CreationDate as DATE)) MaxDate
FROM ItemPriceListMap
) M ON CAST(L.CreationDate as DATE) <> M.MaxDate
Try this :
DELETE L
FROM ItemPriceListMap L
WHERE CreationDate <> (SELECT MAX(CreationDate) MaxDate
FROM ItemPriceListMap LL
WHERE L.ItemPriceListUID3 = LL.ItemPriceListUID3)
Note : Take backup of your data first.
Use a CTE and a row_number
with CTE as
(
select a1.*, row_number() over(
partition by ItemPriceListUID3 -- remove this if you don't need the grouping
order by CreationDate desc) as R_ORD
from ItemPriceListMap a1
)
delete
from CTE
where R_ORD > 1

How to remove duplicate entries in my query?

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

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 )