Select latest date - sql-server-2008-r2

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

Related

find max value for specific column while still seeing other columns

For tables patient and labh
patient
id lastname
19 patientone
20 patienttwo
patientid lastname loinc datetime numerical
19 patientone 4548-4 2014-05-15 00:00:00 6.5
19 patientone 4548-4 2015-05-15 00:00:00 7.5
19 patientone 4548-4 2016-05-15 00:00:00 3.5
19 patientone 4548-4 2017-05-15 00:00:00 5.5
19 patientone 5000-3 2018-05-15 00:00:00 123
20 patienttwo 4548-4 2013-05-15 00:00:00 2.5
20 patienttwo 4548-4 2012-05-15 00:00:00 1.5
20 patienttwo 4548-4 2011-05-15 00:00:00 9.5
20 patienttwo 4548-4 2010-05-15 00:00:00 3.5
Desired output:
patientid lastname datetime numerical
19 patientone 2017-05-15 00:00:00 5.5
20 patienttwo 2013-05-15 00:00:00 2.5
The labh table hold lab values(numerical), the type of lab (loinc) and when they were done (datetime). I'd like to query for the most recent value of loinc=4548-4 , and i'd like the output to show both the date and the value.
i've tried this below and it shows the most recent dates, but I can't see the values (numerical) at the same time. when I add the numerical column, the it shows all the values, not just the most recent.
Select Distinct patient.id, patient.lastname, Max(Date_Trunc('day', labh.datetime)) As "Date" From patient Inner Join labh On patient.id = labh.patientid Where labh.loinc = '4548-4' Group By patient.id, patient.lastname, patient.firstname Order By patient.id
you haven't selected the numerical column in your query. You can use CTE to store the data temporarily through ranking on pratition over patient id and ordering each partition on the basis of date.
So, according to this, you can try:
WITH summary AS (
SELECT p.id as "Patient ID",
p.lastname as "Patient Name",
l.datetime As "Date",
l.numerical as "Numerical",
ROW_NUMBER() OVER (PARTITION BY p.id
ORDER BY l.datetime DESC) AS rank
FROM patient p
Inner Join labh l
On p.id = l.patientid)
SELECT "Patient ID",
"Patient Name",
"Date",
"Numerical"
FROM summary
WHERE rank = 1;
And this will give you:
Patient ID
Patient Name
Date
Numerical
19
patientone
2017-05-15T00:00:00.000Z
5.5
20
patienttwo
2013-05-15T00:00:00.000Z
2.5
UPDATE
As you've updated the question and changed the expectation, the modified query will be nothing but adding a where condition inside cte construction:
WITH summary AS (
SELECT p.id as "Patient ID",
p.lastname as "Patient Name",
l.datetime As "Date",
l.numerical as "Numerical",
ROW_NUMBER() OVER (PARTITION BY p.id
ORDER BY l.datetime DESC) AS rank
FROM patient p
Inner Join labh l
On p.id = l.patientid
where l.loinc = '4548-4') -- Added this line
SELECT "Patient ID",
"Patient Name",
"Date",
"Numerical"
FROM summary
WHERE rank = 1;
This will give you the same result:
Patient ID
Patient Name
Date
Numerical
19
patientone
2017-05-15T00:00:00.000Z
5.5
20
patienttwo
2013-05-15T00:00:00.000Z
2.5
In order to achieve what you're looking for in Postgres (and other SQL RDBMSes), you need to essentially identify the max value and its corresponding primary key, then join it with the rest of the data set you are looking to retrieve:
SELECT patient.*, labh.*
FROM patient
JOIN labh
ON patient.id = labh.patientid
JOIN (SELECT patientid, max(datetime)
FROM labh
GROUP BY patientid) maxvals
ON maxvals.patientid = labh.patientid AND
maxvals.datetime = labh.datetime

Not getting desired format from Oracle query

I am trying to fetch data from data base in below format,
Month Count
----- -----
201208 124
201209 0
201210 56
201211 25
201212 0
201301 184
201302 0
In database I have entries like,
Month Count
----- -----
201206 56
201208 124
201210 56
201211 25
201301 184
201304 49
Below is my query,
SELECT MONTH, Count
FROM TABLE_NAME
WHERE MONTH BETWEEN 201208 AND 201302
AND ID = 'X'
Output :
Month Count
----- -----
201208 124
201210 56
201211 25
201301 184
Can anyone help me getting data in desired format.
First you should generate full month's sequence between these dates. You can do it with CONNECT BY LEVEL in Oracle. then just JOIN this sequence with your table:
SELECT MonthSeq.MONTH,
NVL(Count,0) Count
FROM TABLE_NAME
RIGHT JOIN
(
SELECT
TO_CHAR(ADD_MONTHS(TO_DATE('201208','YYYYMM'),
(ROWNUM-1))
,'YYYYMM') MONTH
FROM DUAL
CONNECT BY LEVEL<=
MONTHS_BETWEEN(TO_DATE('201302','YYYYMM') ,
TO_DATE('201208','YYYYMM'))+1
) MonthSeq
ON TABLE_NAME.MONTH=MonthSeq.MONTH
ORDER BY MonthSeq.MONTH
SQLFiddle demo
UPD:
Your query from the comment should looks like the following. You should move WHERE condition to the JOIN ON. If you use it in WHERE you don't get rows with zero counts.
SELECT MonthSeq.MONTH,
NVL(SUM(TOTAL_SESSIONS),0) AS SESSIONS
FROM X
RIGHT JOIN
(
SELECT
TO_CHAR(ADD_MONTHS(TO_DATE('201208','YYYYMM'),
(ROWNUM-1))
,'YYYYMM') MONTH
FROM DUAL
CONNECT BY LEVEL<=
MONTHS_BETWEEN(TO_DATE('201302','YYYYMM') ,
TO_DATE('201208','YYYYMM'))+1
) MonthSeq
ON X.MONTH=MonthSeq.MONTH and X.acct_id = 'ABCD'
ORDER BY MonthSeq.MONTH
You need to use TO_DATE function to convert the month field to DATE format. Refer here for more in detail. Try like this,
SELECT TO_CHAR(TO_DATE(MONTH, 'YYYYMM'), 'YYYYMM') month, count
FROM TABLE_NAME
WHERE month BETWEEN TO_DATE('201208', 'YYYYMM') AND TO_DATE('201302', 'YYYYMM')
AND id = 'X'
ORDER BY TO_DATE(month, 'YYYYMM');

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

To calculate min and max of record for huge volume of record

My problem is to get max and minimum date for ABC. I have to do this for around 200 000 records which takes more time. How to improve the performance
ROW_ID DATE C value
----------------------------------------------
1 2012-08-01 00:00:00.0 ABC 87
2 2012-09-01 00:00:00.0 ABC 87
3 2012-10-01 00:00:00.0 ABC 87
4 2012-11-01 00:00:00.0 ABC 87
5 2012-12-01 00:00:00.0 ABC 87
6 2013-01-01 00:00:00.0 CBA 87
7 2013-02-01 00:00:00.0 ABC 87
8 2013-03-01 00:00:00.0 ABC 87
You should be able to do this easily using something like:
select c,
min(date) min_date,
max(date) max_date
from yt
where c='ABC'
group by c;
See SQL Fiddle with Demo.
Edit, since you are attempting to use this data to update another table in Sybase you have a few options. Sybase does not allow derived tables in UPDATE statements so I would suggest using a temp table to get the min/max date for each c and then use this table in your UPDATE with JOIN:
select c,
min(date) min_date,
max(date) max_date
into #temp2
from yt
where c='ABC'
group by c;
update t
set t.min_date = t1.min_date,
t.max_date = t1.max_date
from temp t
inner join #temp2 t1
on t.c = t1.c;
See SQL Fiddle with Demo

help req in basic t-sql

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