Take the last in the query - sql

I have a query like this:
Select *
From Table1 as ad
inner join Table2 as u
on u.employee_ident=ad.employee_ident
inner join Table3 as t
On u.employee_ident=t.employee_ident and u.hire_date=t.hire_date
where DATEDIFF(day,t.term_date,GETDATE() )>=60 AND u.status in ('nohire','1') and u.company_group_abbr_name='ABC'
order by
t.term_date asc
Table3 for the same user has more than one term_date. I want that when I run this query in the moment that the compare will be done in DATEDIFF(day,t.term_date,GETDATE() )>=60 in the part of t.term_date it will take the last one. Actually when I run it it makes the compare with the first one that it finds.
So from the dates 2018, 2020, and 2022 it compares with 2018 and I want it to make the compare with 2022 which is the most recent one. How can I do this?

Try something like this:
WITH T3Latest (
employee_ident,
hire_date,
term_date,
term_rank
)
AS (
SELECT employee_ident,
hire_date,
term_date,
RANK() OVER (
PARTITION BY employee_ident ORDER BY term_date DESC
) term_rank
FROM Table3
)
SELECT *
FROM Table1 AS ad
INNER JOIN Table2 AS u ON u.employee_ident = ad.employee_ident
INNER JOIN T3Latest AS t ON u.employee_ident = t.employee_ident
AND u.hire_date = t.hire_date
WHERE t.term_rank = 1
AND DATEDIFF(day, t.term_date, GETDATE()) >= 60
AND u.STATUS IN (
'nohire',
'1'
)
AND u.company_group_abbr_name = 'ABC'
ORDER BY t.term_date ASC;

Related

SQL Query 1 have count Function and to get data from another SQL Query 2 where memberid is same

My First Query is
SELECT
memberid,
count(*) count
From
dbo.Transactions
group by
dbo.Transactions.MemberID
having
count(memberid) > 1
My query 2 is
SELECT
transactionlog.id,
transactionlog.transactionid,
transactionlog.transactionamount,
transactionlog.transactiondate,
transactions.MemberID,
GymMember.FirstName,
from
dbo.GymMember
inner join Transactions on
GymMember.MemberID = Transactions.MemberId
inner join TransactionLog on
Transactions.Id = TransactionLog.TransactionId
Results of Query 2 are givne in below image
Now i want to have data where query 1 member id and query 2 member id are same
Do you mean find data where the MemberID from the second query exists in the first query? If so please see query below.
SELECT
transactionlog.id,
transactionlog.transactionid,
transactionlog.transactionamount,
transactionlog.transactiondate,
transactions.MemberID,
GymMember.FirstName,
from
dbo.GymMember
inner join Transactions on
GymMember.MemberID = Transactions.MemberId
inner join TransactionLog on
Transactions.Id = TransactionLog.TransactionId
WHERE
Transactions.MemberId IN
(SELECT
memberid
FROM
dbo.Transactions
group by
dbo.Transactions.MemberID
having
count(memberid) > 1))
I was working on it from more than 24 hours and after try and trial i found the solution but Senior can recommend a more proper way to do this My Solution is
SELECT* FROM( SELECT* FROM
(select transactionlog.id, transactionlog.transactionid, transactionlog.transactionamount, transactionlog.transactiondate, transactions.MemberID, GymMember.FirstName, GymMember.CellNumber from dbo.GymMember
inner join Transactions on GymMember.MemberID = Transactions.MemberId
inner join TransactionLog on Transactions.Id = TransactionLog.TransactionId) as MYTABLE where Exists
(select dbo.transactions.memberid,count(dbo.transactions.memberid) From dbo.Transactions Where mytable.MemberID = dbo.Transactions.MemberID group by dbo.Transactions.MemberID having count(dbo.Transactions.MemberID) > 1)) AS mynewtable where convert(datetime,TransactionDate,103) between '2022-09-30 00:00:00' and '2022-10-01 00:00:00'

Remove multiple rows with same ID

So I've done some looking around and wasn't unable to find quite what I was looking for. I have two tables.
1.) Table where general user information is stored
2.) Where a status is generated and stored.
The problem is, is that there are multiple rows for the same users and querying these results in multiple returns. I can't just merge them because they aren't all the same status. I need just the newest status from that table.
Example of the table:
SELECT DISTINCT
TOP(50) cam.UserID AS PatientID,
mppi.DisplayName AS Surgeon,
ISNULL(sci.IOPStatus, 'N/A') AS Status,
tkstat.TrackerStatusID AS Stat_2
FROM
Main AS cam
INNER JOIN
Providers AS rap
ON cam.VisitID = rap.VisitID
INNER JOIN
ProviderInfo AS mppi
ON rap.UnvUserID = mppi.UnvUserID
LEFT OUTER JOIN
Inop AS sci
ON cam.CwsID = sci.CwsID
LEFT OUTER JOIN
TrackerStatus AS tkstat
ON cam.CwsID = tkstat.CwsID
WHERE
(
cam.Location_ID IN
(
'SURG'
)
)
AND
(
rap.IsAttending = 'Y'
)
AND
(
cam.DateTime BETWEEN CONCAT(CAST(GETDATE() AS DATE), ' 00:00:00') AND CONCAT(CAST(GETDATE() AS DATE), ' 23:59:59')
)
AND
(
cam.Status_StatusID != 'Cancelled'
)
ORDER BY
cam.UserID ASC
So I need to grab only the newest Stat_2 from each ID so they aren't returning multiple rows. Each Stat_2 also has an update time meaning I can sort by the time/date that column is : StatusDateTime
One way to handle this is to create a calculated row_number for the table where you need the newest record.
Easiest way to do that is to change your TKSTAT join to a derived table with the row_number calculation and then add a constraint to your join where the RN =1
SELECT DISTINCT TOP (50)
cam.UserID AS PatientID, mppi.DisplayName AS Surgeon, ISNULL(sci.IOPStatus, 'N/A') AS Status, tkstat.TrackerStatusID AS Stat_2
FROM Main AS cam
INNER JOIN Providers AS rap ON cam.VisitID = rap.VisitID
INNER JOIN ProviderInfo AS mppi ON rap.UnvUserID = mppi.UnvUserID
LEFT OUTER JOIN Inop AS sci ON cam.CwsID = sci.CwsID
LEFT OUTER JOIN (SELECT tk.CwsID, tk.TrackerStatusId, ROW_NUMBER() OVER (PARTITION BY tk.cwsId ORDER BY tk.CreationDate DESC) AS rn FROM TrackerStatus tk)AS tkstat ON cam.CwsID = tkstat.CwsID
AND tkstat.rn = 1
WHERE (cam.Location_ID IN ( 'SURG' )) AND (rap.IsAttending = 'Y')
AND (cam.DateTime BETWEEN CONCAT(CAST(GETDATE() AS DATE), ' 00:00:00') AND CONCAT(CAST(GETDATE() AS DATE), ' 23:59:59'))
AND (cam.Status_StatusID != 'Cancelled')
ORDER BY cam.UserID ASC;
Note you need a way to derive what the "newest" status is; I assume there is a created_date or something; you'll need to enter the correct colum name
ROW_NUMBER() OVER (PARTITION BY tk.cwsId ORDER BY tk.CreationDate DESC) AS rn
SQL Server doesn't offer a FIRST function, but you can reproduce the functionality with ROW_NUMBER() like this:
With Qry1 (
Select <other columns>,
ROW_NUMBER() OVER(
PARTITION BY <group by columns>
ORDER BY <time stamp column*> DESC
) As Seq
From <the rest of your select statement>
)
Select *
From Qry1
Where Seq = 1
* for the "newest" record.

SQL Group by colum1 "keep" by datetime

I have the follow table:
ID -- timestamps -- uid
1 -- 12:00 -- 1
2 -- 12:15 -- 1
3 -- 12:30 -- 2
4 -- 12:45 -- 2
Now I need unique uid's by the last timestamps, result have to look like this:
ID -- timestamps -- uid
2 -- 12:15 -- 1
4 -- 12:45 -- 2
If there is any problem with joins, tell me please.
Thats my current SQL Statmant:
SELECT DISTINCT "lists".* FROM "lists" INNER JOIN identifys i WHERE (i.ip
= '1' OR i.session = '2')
And that my ActiveRecord:
List.all.joins("INNER JOIN identifys i")
.where("i.ip = ? OR i.session = ?", ip, session)
.distinct
How about adding Group by to your query? Something along these lines:
select Max(l.ID) as ID, Max(l.timestamps) as timestamps, l.uid
from Lists l INNER JOIN identifys i
WHERE (i.ip = '1' OR i.session = '2')
Group By l.uid
Another possible solution:
SELECT l2.id , a.uid, a.timestamps
FROM
(
SELECT Max(l.timestamps) as timestamps, l.uid
FROM Lists l INNER JOIN identifys i
WHERE (i.ip = '1' OR i.session = '2')
Group By l.uid
) a
Inner Join Lists l2 on a.timestamps = l2.timestamps
In MySQL or SQLite you could use a filtering join, like:
select *
from YourTable yt
join (
select UID
, max(timestamp) as max_timestamp
from YourTable
group by
UID
) filter
on yt.UID = filter.UID
and yt.timestamp = filter.max_timestamp
In a datase that supports windowing functions, like PostgreSQL, Oracle or SQL Server, you could:
select *
from (
select row_number() (
partition by UID
order by timestamp desc) as rn
, *
from YourTable
) SubQueryAlias
where rn = 1 -- Only latest row per UID

SQL Query For Customers Not Used For Last 3 Years

I THINK I'm having some trouble.
I'm trying to query 2 tables for customers that haven't been used on the table for the last 3 Years. The data consists of data ranging for 7+ years, so customers are used multiple times.
I think the issue with my current query: It's finding data of customers not used in the last 3 years... but it's not accounting for if there is also data of the customer within the last 3 years as well.
Can someone possibly help me? I'm guessing the answer is to use only the data of the customer with the latest date and ignore previous data.
SELECT DISTINCT
tbl_Customer.CustomerID
, tbl_Customer.CustomerName
, Table1.ImportDate
, Table2.ImportDate
FROM
tbl_Customer
LEFT JOIN
Table1 ON tbl_Customer.CustomerName = Table1.CustomerName
LEFT JOIN
Table2 ON tbl_Customer.CustomerName = Table2.CustomerName
WHERE
(((DateAdd("yyyy", 3, [Table2].[ImportDate])) < Now())
AND
((DateAdd("yyyy", 3, [Table1].[ImportDate])) < Now()))
ORDER BY
Table1.ImportDate DESC,
Table2.ImportDate DESC;
The core problem with the initial query is that, for no imports (which will happen for "no order" customers) the condition
DateAdd("yyyy", 3, ImportDate) < Now()
--> DateAdd("yyyy", 3, NULL) < Now()
--> NULL < Now()
--> NULL (or not true)
is not true. A simple fix is to add a guard
([Table1].[ImportDate] IS NULL
OR DateAdd("yyyy", 3, [Table1].[ImportDate]) < Now())
around such expressions or to coalesce the NULL value before using it.
The ordering will also be wrong, as that means order by one value and then the other, not "by the greater of both" values. Compare with
ORDER BY
IIF(Table1.ImportDate > Table2.ImportDate, Table1.ImportDate, Table2.ImportDate)
However, I would use a LEFT JOIN on customers/orders, GROUP BY with a MAX on the order dates. Then you can use that result (as a derived subquery) to complete the query asked fairly trivially.
SELECT
c.CustomerID
, MAX(o.ImportDate) as lastImport
FROM tbl_Customer as c
-- The UNION is to simply "normalize" to a single table.
-- (Also, shouldn't the join be on a customer "ID"?)
LEFT JOIN (
SELECT CustomerName, ImportDate from Table1
UNION
SELECT CustomerName, ImportDate from Table2) as o
ON c.CustomerName = o.CustomerName
GROUP BY c.CustomerID
Then,
SELECT s.CustomerID
FROM (thatSubQuery) as s
WHERE
-- no orders
s.lastImport IS NULL
-- only old orders
OR DateAdd("yyyy", 3, s.lastImport) < Now()
ORDER BY s.lastImport
(YMMV with MS Access, this will work in a "real" database ;-)
SELECT DISTINCT
tbl_Customer.CustomerID,
tbl_Customer.CustomerName,
Table1.ImportDate,
Table2.ImportDate
FROM (tbl_Customer
LEFT JOIN Table1
ON tbl_Customer.CustomerName = Table1.CustomerName)
LEFT JOIN Table2
ON tbl_Customer.CustomerName = Table2.CustomerName
WHERE DateAdd("yyyy",3,[Table2].[ImportDate]) < Now()
AND DateAdd("yyyy",3,[Table1].[ImportDate]) < Now()
AND tbl_Customer.CustomerID NOT IN (
SELECT DISTINCT
tbl_Customer.CustomerID,
FROM (tbl_Customer
LEFT JOIN Table1
ON tbl_Customer.CustomerName = Table1.CustomerName)
LEFT JOIN Table2
ON tbl_Customer.CustomerName = Table2.CustomerName
WHERE DateAdd("yyyy",3,[Table2].[ImportDate]) >= Now()
AND DateAdd("yyyy",3,[Table1].[ImportDate]) >= Now()
)
ORDER BY Table1.ImportDate DESC , Table2.ImportDate DESC;
Based on what I can infer from your query about your data structure, I think you want something like this:
DECLARE #CutOff DateTime
SET #CutOff = DATEADD(y, -3 GETDATE())
SELECT tbl_Customer.CustomerID, tbl_Customer.CustomerName
WHERE (CustomerName IN
(SELECT CustomerName FROM Table1 WHERE ImportDate < #CutOff))
OR
(CustomerName IN
(SELECT CustomerName FROM Table2 WHERE ImportDate < #CutOff)))
AND CustomerName NOT IN
(SELECT CustomerName FROM Table1 WHERE ImportDate > #CutOff)
AND CustomerName NOT IN
(SELECT CustomerName FROM Table2 WHERE ImportDate > #CutOff)

How to use multiple count and where condition sql server 2008?

I have this two query
1.
select CL_Clients.cl_id,CL_Clients].cl_name,COUNT(*) AS number_of_orders
from CL_Clients,CLOI_ClientOrderItems
where CL_Clients.cl_id=CLOI_ClientOrderItems.cl_id
group by CL_Clients.cl_name,CL_Clients.cl_id
2.
select CL_Clients.cl_id,count(cloi_current_status) as dis
from CLOI_ClientOrderItems,CL_Clients
where cloi_current_status]='12'
and CL_Clients.cl_id=CLOI_ClientOrderItems.cl_id
group by CL_Clients.cl_name,CL_Clients.cl_id,CLOI_ClientOrderItems.cloi_current_status
i have this column i need to put count function and where condition
[cloi_current_status]
166
30
30
30
150
150
150
150
150
150
150
Quite simple, you just encapsulate the queries and give their result sets an alias and then do a JOIN between their aliases on the column that is common. (In the query below I assume you'll be joining by client id)
SELECT *
FROM (
SELECT CL_Clients.cl_id,
CL_Clients].cl_name,
COUNT(*) AS number_of_orders
FROM CL_Clients,
CLOI_ClientOrderItems
WHERE CL_Clients.cl_id = CLOI_ClientOrderItems.cl_id
GROUP BY CL_Clients.cl_name,
CL_Clients.cl_id
) A
INNER JOIN (
SELECT CL_Clients.cl_id,
count(cloi_current_status) AS dis
FROM CLOI_ClientOrderItems,
CL_Clients
WHERE cloi_current_status] = '12'
AND CL_Clients.cl_id = CLOI_ClientOrderItems.cl_id
GROUP BY CL_Clients.cl_name,
CL_Clients.cl_id,
CLOI_ClientOrderItems.cloi_current_status
) B
ON A.cl_id = B.cl_id
WHERE ...
GROUP BY ...
This will be treated as a separate result set, so you can also filter results with a WHERE or just a GROUP BY, just like in a normal SELECT.
UPDATE:
To answer the question in your comments, when you join two tables that have a column with the same value and use
SELECT * FROM A INNER JOIN B the * will show all columns returned by the join, meaning all columns from A and all columns from B, this is why you have duplicate columns.
If you want to filter the columns returned you can specifiy which columns you want returned. So, in your case, the top SELECT * can be replaced with
SELECT A.cl_id, A.cl_name, A.number_of_orders, B.dis so, your query becomes:
SELECT A.cl_id, A.cl_name, A.number_of_orders, B.dis
FROM (
SELECT CL_Clients.cl_id,
CL_Clients].cl_name,
COUNT(*) AS number_of_orders
FROM CL_Clients,
CLOI_ClientOrderItems
WHERE CL_Clients.cl_id = CLOI_ClientOrderItems.cl_id
GROUP BY CL_Clients.cl_name,
CL_Clients.cl_id
) A
INNER JOIN (
SELECT CL_Clients.cl_id,
count(cloi_current_status) AS dis
FROM CLOI_ClientOrderItems,
CL_Clients
WHERE cloi_current_status] = '12'
AND CL_Clients.cl_id = CLOI_ClientOrderItems.cl_id
GROUP BY CL_Clients.cl_name,
CL_Clients.cl_id,
CLOI_ClientOrderItems.cloi_current_status
) B
ON A.cl_id = B.cl_id
UPDATE #2:
For your last question, you need to GROUP BY at the end of the big query and use a HAVING condtion, like this:
GROUP BY A.cl_id, A.cl_name, A.number_of_orders, B.dis
HAVING COUNT(cloi_current_status) > 100
All depends on what data you are trying to get, but you can go about it like this.
SELECT Column_x, Column_y, etc..
FROM ClL_Clients a
JOIN (select CL_Clients.cl_id,CL_Clients].cl_name,COUNT(*) AS number_of_orders
from CL_Clients,CLOI_ClientOrderItems
where CL_Clients.cl_id=CLOI_ClientOrderItems.cl_id
group by CL_Clients.cl_name,CL_Clients.cl_id) b
on a.cl_id = b.cl_id
JOIN (select CL_Clients.cl_id,count(cloi_current_status) as dis
from CLOI_ClientOrderItems,CL_Clients
where cloi_current_status]='12'
and CL_Clients.cl_id=CLOI_ClientOrderItems.cl_id
group by CL_Clients.cl_name,CL_Clients.cl_id,CLOI_ClientOrderItems.cloi_current_status) c
on a.cl_id = c.cl_id
Group by BLAH BLAH
Hope this gets you in the right direction.