help req in basic t-sql - tsql

Below is a table.
stu_id meet_doc_id doc_name stu_name dob value date
101 0104 AD AM 15/06/1950 LMDO 2011-02-15
101 0105 AD AM 15/06/1950 CLEAR 2011-02-18
101 0106 AD AM 15/06/1950 CLEAR 2011-02-25
102 0107 AD AK 12/08/1987 CLEAR 2011-03-28
102 0108 AD AK 12/08/1987 LDMO 2011-04-29
103 0109 PK LMP 13/07/1970 CLEAR 2011-03-28
103 0110 PK LMP 13/07/1970 CLEAR 2011-05-12
What will be the resulting query if I expect to see a result set of
stu_id meet_doc_id doc_name stu_name dob value date
101 0104 AD AM 15/06/1950 LMDO 2011-02-15
102 0107 AD AK 12/08/1987 CLEAR 2011-03-28
103 0110 PK LMP 13/07/1970 CLEAR 2011-05-12

Your table looks extremely un-normalised with lots of repeating groups but I think you need
;WITH CTE
AS (SELECT stu_id,
meet_doc_id,
doc_name,
stu_name,
dob,
value,
date,
ROW_NUMBER () OVER (PARTITION BY stu_id ORDER BY meet_doc_id) AS
RN
FROM YourTable)
select stu_id,
meet_doc_id,
doc_name,
stu_name,
dob,
value,
date
FROM CTE
WHERE RN = 1

Related

Window Function For Consecutive Dates

I want to know how many users were active for 3 consecutive days on any given day.
e.g on 2022-11-03, 1 user (user_id = 111) was active 3 days in a row. Could someone please advise what kind of window function(?) would be needed?
This is my dataset:
user_id
active_date
111
2022-11-01
111
2022-11-02
111
2022-11-03
222
2022-11-01
333
2022-11-01
333
2022-11-09
333
2022-11-10
333
2022-11-11
If you are confident there are no duplicate user_id + active_date rows in the source data, then you can use two LAG functions like this:
SELECT user_id,
active_date,
CASE WHEN DATEADD(day, -1, active_date) = LAG(active_date, 1) OVER (PARTITION BY user_id ORDER BY active_date)
AND DATEADD(day, -2, active_date) = LAG(active_date, 2) OVER (PARTITION BY user_id ORDER BY active_date)
THEN 'Yes'
ELSE 'No'
END AS rowof3
FROM your_table
ORDER BY user_id, active_date;
If there might be duplication, use this FROM clause instead:
FROM (SELECT DISTINCT user_id, active_date :: DATE FROM your_table)

postgresql select rows from same table twice

I want to compare deposit for each person in the table.
and return all the rows where the deposit field is decreased.
Here is what I have done so far;
The customer table is;
person_id employee_id deposit ts
101 201 44 2021-09-30 10:12:19+00
100 200 45 2021-09-30 10:12:19+00
101 201 47 2021-09-30 09:12:19+00
100 200 21 2021-09-29 10:12:19+00
104 203 54 2021-09-27 10:12:19+00
and as a result I want is;
person_id employee_id deposit ts
101 201 44 2021-09-30 10:12:19+00
SELECT person_id,
employee_id,
deposit,
ts,
lag(deposit) over client_window as pre_deposit,
lag(ts) over client_window as pre_ts
FROM customer
WINDOW client_window as (partition by person_id order by ts)
ORDER BY person_id , ts
so it returns table with the following results;
person_id employee_id deposit ts pre_deposit pre_ts
101 201 44 2021-09-30 10:12:19+00 47 2021-09-30 09:12:19+00
100 200 45 2021-09-30 10:12:19+00 21 2021-09-29 10:12:19+00
101 201 47 2021-09-30 09:12:19+00 null null
100 200 21 2021-09-29 10:12:19+00 null null
104 203 54 2021-09-27 10:12:19+00 null null
SELECT person_id,
employee_id,
deposit,
ts,
lag(deposit) over client_window as pre_deposit,
lag(ts) over client_window as pre_ts
FROM customer
WINDOW client_window as (partition by person_id order by ts)
WHERE pre_deposit > deposit //this returns column not found for pre_deposit
ORDER BY person_id , ts
so far somehow I need to select the same table again to be able to apply this condition;
where pre_deposit > deposit
what does it make sense here?
union? outer-join? left-join? right-join?
Use your query as a subquery and filter the results:
SELECT person_id, employee_id, deposit, ts
FROM (
SELECT *, lag(deposit) over client_window as pre_deposit
FROM customer
WINDOW client_window as (partition by person_id order by ts)
) t
WHERE deposit < pre_deposit
ORDER BY person_id, ts;
See the demo.

How do I select the min opendate from a list of duplicates?

I have 3 columns. SSN|AccountNumber|OpenDate
1 SSN may have multiple AccountNumbers
Each AccountNumber has a corresponding OpenDate
In my list I have many SSN's, each containing several account numbers which may have been opened on different days.
I want the results of my query to be SSN|earlest OpenDate|AccountNumber that corresponds with the earliest opendate.
I'm dealing with about 200,000 records.
EDIT: First I did
select SSN, min(OpenDate), AcctNumber from Table Group By SSN, AccountNumber
but that didn't quite give me the correct data.
The raw data gives me something like this:
SSN | AcctNumber | OpenDate
---------------------------
10 101 Jan
10 102 Feb
10 103 Mar
Where I got 10, Jan, and AccNumber 102 which is not the account number that is associated with Jan OpenDate After looking at others, I found that the account number I got was just one of the account numbers associated with that SSN rather than the one that corresponds with the min(OpenDate)
WITH CTE AS ( SELECT SSN, AcctNumber, OpenDate, ROW_NUM() OVER (PARTITION BY SSN ORDER BY OpenDate DESC) AS RN ) SELECT SSN, AcctNumber, OpenDate FROM CTE WHERE RN=1;
If your table is like this:
SSN | AcctNumber | OpenDate
---------------------------
10 101 April
10 101 May
10 102 April
20 201 June
20 201 July
Do you want your query to return this?
SSN | AcctNumber | OpenDate
---------------------------
10 101 April
10 102 April
20 201 June
Then you would use this query:
select ssn, min(OpenDate), acctNumber from tbl group by ssn, acctNumber
You can try this..
select SSN , AcctNumber, OpenDate
from (SELECT SSN , AcctNumber, OpenDate
, ROW_NUMBER() OVER ( PARTITION BY SSN, ORDER BY OpenDate ASC ) AS RN
FROM table) AS temp
WHERE temp.RN= 1

How to Count consecutive dates

I'm look for a query in T-Sql to count the number of consecutive dates, backwards where the pop is the same, starting at the latest date and stopping when there is a gap in the date.
This is an example of the data:
Name village Population Date
Rob village1 432 01/07/2013
Rob village2 432 30/06/2013
Rob village3 432 29/06/2013
Rob village3 432 28/06/2013
Rob village3 432 27/06/2013
Rob village3 430 26/06/2013
Rob village3 430 25/06/2013
Rob village3 430 24/06/2013
Rob village3 430 23/06/2013
Rob village3 425 22/06/2013
Rob village3 422 21/06/2013
Rob village3 422 20/06/2013
Rob village3 411 19/06/2013
Harry Village1 123 01/07/2013
Harry Village2 123 30/06/2013
Harry Village3 122 29/06/2013
Pat Village1 123 01/07/2013
Pat Village2 123 30/06/2013
Pat Village3 123 29/06/2013
Pat Village4 100 20/06/2013
Tom Village1 123 01/07/2013
Tom Village2 123 30/06/2013
Tom Village3 123 29/06/2013
Tom Village4 123 28/06/2013
I would expect to get the following results:
Rob 5
Harry 2
Pat 3
Tom 3
The data should be more complex, but there will be 1000's of rows, 100's per person and groups of pop with consecutive dates, but i only want the first set of consecutive dates with the same pop, from the latest downwards.
with dd as
(
select distinct * from table
);
select name, max(count) + 1
from
(
select t1.name, t1.village, t1.pop, count(*) as count
from dd t1
join dd t2
on t2.village = t1.village
and t2.pop = t1.pop
and t2.pop = t1.pop
and t2.date = dateadd(day,-1,t1.date)
group by t1.name, t1.village, t1.pop
) dates
group by name
;with a as
(
select name, village, population, date, cast(date as datetime) + dense_rank() over(partition by Population, name order by date desc) grp
from <your table>
), b as
(
select name, village, population, date, dense_rank() over (partition by name order by grp desc) rk
from a
)
select name, count(distinct date) from b
where rk = 1
group by name

Select latest date

SELECT
distinct
HRM_Employee.EmployeeId EmployeeXId,
([HRM_Employee].[FirstName] +' '+ISNULL([HRM_Employee].[MiddleName],' ')+' '+ISNULL([HRM_Employee].[LastName],' ')) AS FirstName
-- ,[FirstName]
,[HRM_Employee].[MiddleName]
,[HRM_Employee].[LastName]
,[HRM_Employee].[Code]
,[HRM_Employee].[UserName]
,[HRM_Employee].[Password]
,[HRM_Employee].[DateOfBirth]
,[HRM_Employee].[OriginalBirthDate]
,[HRM_Employee].[Gender]
,[HRM_Employee].[BloodGroup]
,[HRM_Employee].[Height]
,[HRM_Employee].[MaritalStatus]
,[HRM_Employee].[DateOfMarriage]
,[HRM_Employee].[IdentificationMark1]
,[HRM_Employee].[IdentificationMark2]
,[HRM_Employee].[Religion]
,(SELECT [A].[FirstName] +' '+ [A].[MiddleName] +' '+ [A].[LastName]
FROM [dbo].[HRM_Employee] [A] WHERE [A].EmployeeId = [HRM_Transfer].[ReportingOfficerXId]
) [PersonInCharge]
,[HRM_Department].[Name] [DepartmentName]
,[HRM_Branch].[Name] [BranchName]
,[HRM_Division].[Name] [DivisionName]
,[HRM_Designation].[Name] [DesignationName]
,HRM_Transfer.TransferDate
from HRM_Employee
LEFT join [dbo].[HRM_Division]
ON [HRM_Employee].DivisionXId = [HRM_Division].DivisionId
JOIN [dbo].[HRM_Designation]
ON [HRM_Employee].DesignationXId = [HRM_Designation].DesignationId
JOIN [HRM_Department]
ON [HRM_Employee].[DepartmentXId] = [HRM_Department].[DepartmentId]
JOIN [HRM_Branch]
ON [HRM_Employee].[BranchXId] = [HRM_Branch].[BranchId]
INNER JOIN HRM_Transfer
ON HRM_Transfer.EmployeeXId=HRM_Employee.EmployeeId
WHERE
Convert(varchar(11),HRM_Transfer.TransferDate,103) <=Convert(varchar(11), getdate(),103)
END
When I excecute this i got the output as follows
EmployeeXId FirstName TransferDate
34 Ambarish V 2012-08-09 00:00:00.000
54 Anil N P 2012-08-09 00:00:00.000
55 Ann Rose Abraham 2012-08-08 00:00:00.000
55 Ann Rose Abraham 2012-08-09 00:00:00.000
74 Anees M S 2012-08-09 00:00:00.000
From this I want to display data with latest Transfer date only. That is in EmployeeId 55 I need to display data with Transfer date 2012-08-09 00:00:00.000 only. What modification is I want to do in above SP to get required answer?. Please help me to solve this.
Group by EmployeeXId and select MAX(TransferDate).