Select a Row with Max of CreatedOn group by a criteria - sql

select
Container, CreatedOn, *
from
Inventory_container
where
container in (select IC.Container
from INVENTORY_CONTAINER IC
inner join CONTAINER C on IC.Container = C.Container
where C.ContainerClassID = '100000011'
group by IC.Container
having count(IC.Container) >= 2)
Below is the Result of the Query:
As you can see there are similar containers with 2 rows
I want to select the row with the latest createdon.
Please help editing my query.

i think a sub-query and join would help you
select iC.* from INVENTORY_CONTAINER IC inner join
inner join
(
select IC.Container,max(IC.CreatedOn) as CreatedOn
from INVENTORY_CONTAINER IC
inner join CONTAINER C on IC.Container = C.Container
where C.ContainerClassID = '100000011'
group by IC.Container
having count(IC.Container) >= 2
) t on IC.Container=t.Container and IC.CreatedOn=t.CreatedOn

If you are using SQL Server try below query:
SELECT *
FROM (
SELECT *, ROW_NUMBER()OVER(PARTITION BY Container ORDER BY CreatedOn) AS RowNo
FROM INVENTORY_CONTAINER IC INNER JOIN CONTAINER C ON
IC.Container=C.Container
WHERE C.ContainerClassID='100000011'
GROUP BY IC.Container,CreatedOn
HAVING COUNT(IC.Container)>=2
) AS T
WHERE RowNo = 1

You need to write one more subquery to your query.
select
Container,CreatedOn, *
from
Inventory_container
where
container in (select IC.Container
from INVENTORY_CONTAINER IC
inner join CONTAINER C on IC.Container = C.Container
where C.ContainerClassID = '100000011'
and IC.CreatedOn=
(select max(IC1.CreatedOn) from INVENTORY_CONTAINER IC1
where IC1.container=IC.container));
group by IC.Container
having count(IC.Container) >= 2 ;
I am assuming that the query which you have mentioned is syntactically correct as per your DB design.

Try the following query-:
With CTE as
(
SELECT *, ROW_NUMBER()OVER(PARTITION BY Container ORDER BY CreatedOn desc) AS RN
FROM INVENTORY_CONTAINER IC INNER JOIN CONTAINER C ON
IC.Container=C.Container
WHERE C.ContainerClassID='100000011'
GROUP BY IC.Container
HAVING COUNT(IC.Container)>=2
)select * from CTE where RN=1
SQL Server

Related

How to find duplicate rows from three tables using two columns

—oracle sql-
Select *
From Client cl, Contact c, Location l
Where l.locID = c.locID
and cl.clientID = l.clientID
I want to find more than one occurrences(duplicates) using combined columns of locID and clientID
We can use aggregation here:
SELECT cl.clientID, l.locID
FROM Client cl
INNER JOIN Location l ON l.clientID = cl.clientID
INNER JOIN Contact c ON c.locID = l.locID
GROUP BY cl.clientID, l.locID
HAVING COUNT(*) > 1;
Note that I also refactored your query to use explicit joins.
To see all columns, use this version:
WITH cte AS (
SELECT cl.clientID, l.locID, -- add more columns here
COUNT(*) OVER (PARTITION BY cl.clientID, l.locID) cnt
FROM Client cl
INNER JOIN Location l ON l.clientID = cl.clientID
INNER JOIN Contact c ON c.locID = l.locID
)
SELECT *
FROM cte
WHERE cnt > 1;
You can get all the details of the rows using the analytic COUNT function:
SELECT *
FROM (
SELECT cl.clientID,
cl.otherClientColumn,
c.locID,
c.otherContactColumn,
l.otherLocationColumn,
COUNT(*) OVER (PARTITION BY cl.clientID, c.locID) AS num_duplicates
From Client cl
INNER JOIN Contact c
ON (cl.clientID = l.clientID)
INNER JOIN Location l
ON (l.locID = c.locID)
)
WHERE num_duplicates > 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

Getting Latest 3 orders by Supplier ID

I have the following SQL Server code to get information from a combination of 4 tables.
I would like to modify it to only retrieve the latest 3 orders (pmpOrderDate) by supplier (pmpSupplierOrganizationID).
SELECT
PO.pmpPurchaseOrderID, PO.pmpOrderDate, PO.pmpSupplierOrganizationID, O.cmoName
FROM
PurchaseOrders PO
INNER JOIN
PurchaseOrderLines POL ON PO.pmpPurchaseOrderID = POL.pmlPurchaseOrderID
INNER JOIN
Organizations O ON PO.pmpSupplierOrganizationID = O.cmoOrganizationID
INNER JOIN
Parts P ON POL.pmlPartID = P.impPartID
WHERE
P.impPartClassID LIKE 'PUMP%'
Can you please help?
EDIT:
I wasn't fully clear on my actual requirements. To clarify further, what I need in the end is to display the latest 3 unique Purchase Orders by Supplier ID based on at least one of the PartClassID for the PartID in the PurchaseOrderLines to have criteria of beginning with string 'PUMP'
Use a ROW_NUMBER to partition by pmpSupplierOrganizationID and order by pmpOrderDate.
with cteTopOrders AS (
SELECT PO.pmpPurchaseOrderID, PO.pmpOrderDate, PO.pmpSupplierOrganizationID, O.cmoName,
ROW_NUMBER() OVER(PARTITION BY pmpSupplierOrganizationID ORDER BY pmpOrderDate DESC) AS RowNum
FROM PurchaseOrders PO
Inner Join PurchaseOrderLines POL ON PO.pmpPurchaseOrderID = POL.pmlPurchaseOrderID
Inner Join Organizations O On PO.pmpSupplierOrganizationID = O.cmoOrganizationID
Inner Join Parts P ON POL.pmlPartID = P.impPartID
WHERE P.impPartClassID Like 'PUMP%'
)
SELECT pmpPurchaseOrderID, pmpOrderDate, pmpSupplierOrganizationID, cmoName
FROM cteTopOrders
WHERE RowNum <= 3;
I'm a fan of lateral joins for this . . . cross apply:
select p.*, O.cmoName
from Organizations O cross apply
(select top (3) PO.pmpPurchaseOrderID, PO.pmpOrderDate, PO.pmpSupplierOrganizationID
from PurchaseOrders PO join
PurchaseOrderLines POL
on PO.pmpPurchaseOrderID = POL.pmlPurchaseOrderID join
Parts P
on POL.pmlPartID = P.impPartID
where PO.pmpSupplierOrganizationID = O.cmoOrganizationID and
P.impPartClassID Like 'PUMP%'
order by PO.pmpOrderDate desc
) p
You need a nested row_number to get the three rows per supplier and another OLAP-function on top of it:
with OrderRowNum as
(
SELECT PO.pmpPurchaseOrderID, PO.pmpOrderDate, PO.pmpSupplierOrganizationID, O.cmoName, P.impPartClassID,
row_number()
over (partition by PO.pmpSupplierOrganizationID
order by pmpOrderDate desc) as rn
FROM PurchaseOrders PO
Inner Join PurchaseOrderLines POL ON PO.pmpPurchaseOrderID = POL.pmlPurchaseOrderID
Inner Join Organizations O On PO.pmpSupplierOrganizationID = O.cmoOrganizationID
Inner Join Parts P ON POL.pmlPartID = P.impPartID
)
, CheckPUMP as
(
select *,
-- check if at least one of the three rows contains PUMP
max(case when impPartClassID Like 'PUMP%' then 1 else 0 end)
over (partition by PO.pmpSupplierOrganizationID) as PUMPflag
from OrderRowNum
where rn <= 3 -- get the last three rows per supplier
)
select *
from CheckPUMP
where flag = 1

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

Use Inner Select value in Where Clause

I have an SQL query that I am trying to use a subs elects value in the outer where clause.
SELECT count(A.[processID]) AS total,
B.[process] AS processName,
(SELECT TOP 1 LocationDesc
FROM dbo.EmployeeTable_Historical AS D
WHERE C.leaver = D.QID
ORDER BY meta_logDate DESC)
FROM dbo.attritionDataPrevention AS A
INNER JOIN
attritionProcesses AS B
ON A.[processID] = B.[processID]
INNER JOIN
dbo.attritionData AS C
ON A.[recordID] = C.recordID
WHERE D.[locationDesc] IN (SELECT location
FROM #table)
AND YEAR(C.[leaveDate]) = #year
GROUP BY B.[processID]
ORDER BY total DESC
FOR XML PATH ('type'), TYPE, ELEMENTS, ROOT ('root');
In my main WHERE clause, it is saying that it cant BIND WHERE D.[locationDesc]. The S alias is in a sub query so I'm not too sure how to use its value.
UPDATE
Per suggestion, I changed the code to the following:
SELECT count(A.[processID]) AS total,
B.[process] AS processName
FROM dbo.attritionDataPrevention AS A
INNER JOIN
attritionProcesses AS B
ON A.[processID] = B.[processID]
INNER JOIN
dbo.attritionData AS C
ON A.recordID = C.recordID,
(
SELECT TOP 1 D.LocationDesc
FROM dbo.EmployeeTable_Historical AS D
WHERE C.leaver = D.QID
ORDER BY D.[meta_logDate] DESC
) AS D
WHERE D.locationDesc IN (SELECT location FROM #table)
AND YEAR(C.[leaveDate]) = #year
GROUP BY B.[process]
ORDER BY total DESC
FOR XML PATH ('type'), TYPE, ELEMENTS, ROOT ('root');
The only issue now is WHERE C.leaver wont bind to the inner join.
Try this :
SELECT count(A.[processID]) Over (Partition by B.[processID]) AS total,
B.[process] AS processName,
(SELECT TOP 1 LocationDesc
FROM dbo.EmployeeTable_Historical AS D
WHERE C.leaver = D.QID
AND D.[locationDesc] IN (SELECT location FROM #table)
ORDER BY meta_logDate DESC)
FROM dbo.attritionDataPrevention AS A
INNER JOIN
attritionProcesses AS B
ON A.[processID] = B.[processID]
INNER JOIN
dbo.attritionData AS C
ON A.[recordID] = C.recordID
WHERE YEAR(C.[leaveDate]) = #year
ORDER BY total DESC
FOR XML PATH ('type'), TYPE, ELEMENTS, ROOT ('root');