Use Inner Select value in Where Clause - sql

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');

Related

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

What should I do if I want to group the data using column but want to put extra columns too in select statement?

update s
set s.Date = f.Date
from SecondDates s
inner join (select Location, max(Date) Date
from FirstDates
group by Location) f on f.Location = s.Location
What if more columns in SecondTable needs to be updated from FirstTable? E.g. Set s.Name= f.Name, s.CellNo= f.CellNo.
I know that we can select more columns in select statement i.e. f but grouping them would present unwanted results.
If the are unique, you can also pick them through the sub query as below. This will only work if there only one Unique Name and CellNo available for a single location. Other case this will not work.
UPDATE s
SET s.Date = f.Date,
s.Name= f.Name,
s.CellNo= f.CellNo
FROM SecondDates s
INNER JOIN (
SELECT Location,name,cellno,
MAX(Date) Date
FROM FirstDates
GROUP BY name,cellno,Location
) f
ON f.Location = s.Location
APPLY is probably the simplest solution:
update s
set s.Date = fd.Date,
s.Name = fd.Name,
. . .
from SecondDates s cross apply
(select top (1) fd.*
from FirstDates
where f.Location = s.Location
order by f.date desc
) fd;
Another method would use row_number():
update s
set s.Date = fd.Date,
s.Name = fd.Name,
. . .
from SecondDates s join
(select fd.*,
row_number() over (partition by location order by date desc) as seqnum
) fd
on f.Location = s.Location
where seqnum = 1;
Instead of GROUP BY Location use NOT EXISTS to get the row with the last Date for each Location from FirstDates:
update s
set s.Date = f.Date, s.name = f.name, s.cellno = f.cellno
from SecondDates s inner join (
select f.* from FirstDates f
where not exists (
select 1 from FirstDates
where Location = f.Location and Date > f.Date
)
) f on f.Location = s.Location

Select a Row with Max of CreatedOn group by a criteria

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

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)))

Using MAX for date but adding column to group on 'breaks' the query - sub query?

I Have a table which holds date but I need to know the latest date where a condition is true per location, only issue is once I add a column called 'notes' it breaks the query and returns too many rows, current query is ...
SELECT
Location,
MAX(date) AS date,
type,
notes
FROM NotesTable a
INNER JOIN Location b on a.LocationID = b.LocationID
INNER JOIN Type c on a.typeid = c.typeid
WHERE typeid <> 8
GROUP BY Location, type, notes
If I comment out the notes column then it works fine but as soon as I add that to the grouping it then returns more rows than required.
Have tried using a subquery but still cant get it working, subquery below
SELECT
r.location,
r.date,
r.type,
t.notes
FROM (SELECT Location, MAX(date), type
FROM NotesTable a INNER JOIN Location b on a.LocationID = b.LocationID
INNER JOIN Type c on a.typeid = c.typeid
WHERE typeid <> 8
GROUP BY location,type
) r
INNER JOIN NotesTable t ON t.date = r.date
Anyone got any other suggestions?
select * from
(
SELECT Location,Date, Type, Notes, Row_Number() Over (Partition By Location, Type order by date desc) RN
FROM
NotesTable a
INNER JOIN Location b on a.LocationID = b.LocationID
INNER JOIN Type c on a.typeid = c.typeid
WHERE typeid <> 8
) v
WHERE rn = 1
Your query is almost correct, you need to add this additional condition in ON clause
AND
t.location = r.location AND
t.type = r.type
full query,
SELECT r.location
, r.DATE
, r.type
, t.notes
FROM (
SELECT Location
, MAX(DATE) maxDate
, type
FROM NotesTable a
INNER JOIN Location b
ON a.LocationID = b.LocationID
INNER JOIN Type c
ON a.typeid = c.typeid
WHERE typeid <> 8
GROUP BY location
, type
) r
INNER JOIN NotesTable t
ON t.DATE = r.maxDate AND
t.location = r.location AND
t.type = r.type