SQL INNER JOIN DISTINCT with max function - sql

I have the tables tbMeasurement and tbPatientMeasurement .
tbMeasurement
MeasurementIDP
MeasurementName
tbPatientMeasurement
PatientMeasurementIDP
MeasurementIDF
MeasurementValue
Taken (Datetime)
When doing the following query:
SELECT DISTINCT dbo.tbMeasurement.MeasurementName
, dbo.tbPatientMeasurement.MeasurementValue
, dbo.tbPatientMeasurement.Taken
FROM dbo.tbMeasurement
INNER JOIN dbo.tbPatientMeasurement
ON dbo.tbMeasurement.MeasurementIDP = dbo.tbPatientMeasurement.MeasurementIDF
This returns a double entry of one of the MeasurementName.
and i also want MeasurementName,MeasurementValue by max Taken(datetime).

Try this one -
SELECT DISTINCT
m.MeasurementName
, p2.MeasurementValue
, p2.Taken
FROM dbo.tbMeasurement m
JOIN (
SELECT
p.MeasurementValue
, Taken = MAX(p.Taken)
FROM dbo.tbPatientMeasurement p
GROUP BY m.MeasurementName, p.MeasurementValue
) p2 ON m.MeasurementIDP = p2.MeasurementIDF

SELECT
m.MeasurementName
, p.MeasurementValue
, a.Taken
FROM dbo.tbMeasurement m
INNER JOIN dbo.tbPatientMeasurement p ON m.MeasurementIDP = p.MeasurementIDF
INNER JOIN
(
select MeasurementIDF,MAX(Taken) as taken
from tbPatientMeasurement
group by MeasurementIDF
) a on a.MeasurementIDF=p.MeasurementIDF and a.taken=p.Taken

Related

SQL Server aggregate function without group by

I want to include tcon.Inductive_Injection_Hours, tcon.Capacitive_Injection_Hours without applying group by. How can I do that?
SELECT
bp.Serial_Number,
tcon.Serial_Number AS ConverterSerialNumber,
MAX(tcon.Time_Stamp) AS DateStamp,
tcon.Inductive_Injection_Hours,
tcon.Capacitive_Injection_Hours
FROM
dbo.Bypass AS bp
INNER JOIN
dbo.Converter AS c ON bp.Bypass_ID = c.Bypass_ID
INNER JOIN
dbo.Converter_Tel_Data AS tcon ON c.Converter_ID = tcon.Converter_ID
WHERE
(bp.Site_ID = 7)
GROUP BY
bp.Serial_Number, tcon.Serial_Number,
tcon.Inductive_Injection_Hours, tcon.Capacitive_Injection_Hours
ORDER BY
ConverterSerialNumber
I have figured it out.
select [data].Serial_Number,Time_Stamp,Inductive_Injection_Hours,Capacitive_Injection_Hours,b.Serial_Number from Converter_Tel_Data as [data]
inner join dbo.Converter AS c On [data].Converter_ID = c.Converter_ID
inner join dbo.Bypass as b on c.Bypass_ID = b.Bypass_ID
WHERE
(Time_Stamp = (SELECT MAX(Time_Stamp) FROM Converter_Tel_Data WHERE Converter_ID = [data].Converter_ID)) And ([data].Site_ID=7)
ORDER BY [data].Serial_Number
You can use row_number - either in a CTE/derived table or using a trick with TOP 1.
Select Top 1 With Ties
bp.Serial_Number
, tcon.Serial_Number AS ConverterSerialNumber
, tcon.Time_Stamp AS DateStamp
, tcon.Inductive_Injection_Hours
, tcon.Capacitive_Injection_Hours
From dbo.Bypass AS bp
Inner Join dbo.Converter AS c On bp.Bypass_ID = c.Bypass_ID
Inner Join dbo.Converter_Tel_Data AS tcon ON c.Converter_ID = tcon.Converter_ID
Where bp.Site_ID = 7
Order By
row_number() over(Partition By bp.Serial_Number Order By tcon.Time_Stamp desc)
This should return the latest row from the tconn table for each bp.Serial_Number.

Need to select ONLY if visiting one location

In the following SQL, it was looking at only those vouchers from location_ID = 5. How can I code that, I ONLY want from a Patient_ID who ONLY visited location_ID 5?
SELECT "Vouchers"."Patient_ID", "vwGenPatInfo"."Patient_Number",
"Practitioners"."Practitioner_ID", "Practitioners"."First_Name",
"Practitioners"."Last_Name", "vwGenPatInfo"."Patient_First_Name",
"vwGenPatInfo"."Patient_Last_Name", "vwGenPatInfo"."Patient_DOB",
"vwGenPatInfo"."Patient_Sex", "Vouchers"."Carrier_ID",
"Vouchers"."Billing_Date", "Vouchers"."Patient_Policy_ID",
"Vouchers"."Location_ID"
FROM ("Ntier_70751"."PM"."vwGenPatInfo" "vwGenPatInfo"
INNER JOIN "Ntier_70751"."PM"."Vouchers" "Vouchers"
ON "vwGenPatInfo"."Account_ID"="Vouchers"."Account_ID")
INNER JOIN "Ntier_70751"."PM"."Practitioners" "Practitioners"
ON "Vouchers"."Actual_Prov_Practitioner_ID"="Practitioners"."Practitioner_ID"
--
WHERE "Vouchers"."Location_ID"=5
Here is one way to do this. I also got rid of all those unneeded double quotes and used proper aliases.
SELECT V.Patient_ID
, gpi.Patient_Number
, P.Practitioner_ID
, P.First_Name
, P.Last_Name
, gpi.Patient_First_Name
, gpi.Patient_Last_Name
, gpi.Patient_DOB
, gpi.Patient_Sex
, V.Carrier_ID
, V.Billing_Date
, V.Patient_Policy_ID
, V.Location_ID
FROM Ntier_70751.PM.vwGenPatInfo gpi
INNER JOIN Ntier_70751.PM.Vouchers V ON gpi.Account_ID = V.Account_ID
INNER JOIN Ntier_70751.PM.Practitioners P ON V.Actual_Prov_Practitioner_ID = P.Practitioner_ID
cross apply
(
select V2.Account_ID
from Ntier_70751.PM.Vouchers V2
where V2.Account_ID = V.Account_ID
group by V2.Account_ID
HAVING MAX(Location_ID) = 5
AND MIN(Location_ID) = 5
) x
Put a condition as say;
WHERE "Vouchers"."Location_ID" = 5
I would go with not exists
SELECT "Vouchers"."Patient_ID", "vwGenPatInfo"."Patient_Number",
"Practitioners"."Practitioner_ID", "Practitioners"."First_Name", "Practitioners"."Last_Name", "vwGenPatInfo"."Patient_First_Name", "vwGenPatInfo"."Patient_Last_Name", "vwGenPatInfo"."Patient_DOB", "vwGenPatInfo"."Patient_Sex", "Vouchers"."Carrier_ID", "Vouchers"."Billing_Date", "Vouchers"."Patient_Policy_ID", "Vouchers"."Location_ID"
FROM "Ntier_70751"."PM"."vwGenPatInfo" "vwGenPatInfo" INNER JOIN
"Ntier_70751"."PM"."Vouchers" "Vouchers"
ON "vwGenPatInfo"."Account_ID" = "Vouchers"."Account_ID" INNER JOIN
"Ntier_70751"."PM"."Practitioners" "Practitioners"
ON "Vouchers"."Actual_Prov_Practitioner_ID" = "Practitioners"."Practitioner_ID"
WHERE "Vouchers"."Location_ID"=5
and not exists (select 1
FROM "Ntier_70751"."PM"."Vouchers" "Vouchers2"
WHERE "Vouchers2"."Patient_ID" = "Vouchers2"."Patient_ID"
AND "Vouchers2"."Location_ID"<>5)
Just using the condition 'WHERE "Vouchers"."Location_ID" = 5'will return all Patient_IDs that visited the that location at least once but not exclusively. There are several ways to do it but the cleanest would be using having max (location_id) <5 and min (location_id) >5

How to handle exception for creating the SQL View in Oracle ?

When I run the following SQL to create a View in a database of 3000 records,
it can work,
but when I run this in a larger database for 9000 records , ORA 01256 and other exceptions mentioning not enough temp spaces and memory are generated after executing for a long time.
If I just run the SQL query starting from the select , it works .. What is happening actually?
CREATE OR REPLACE FORCE VIEW "PM"."LOCATION_TEST" ("GROUPA_TYPE",
"GROUPA_FOLDER_ID", "GROUPA_FOLDER_NAME", "GROUPB_TYPE", "GROUPB_FOLDER_ID",
"GROUPB_FOLDER_NAME", "GROUPC_TYPE", "GROUPC_FOLDER_ID", "GROUPC_FOLDER_NAME",
"GROUPD_TYPE", "GROUPD_FOLDER_ID", "GROUPD_FOLDER_NAME", "GROUPE_TYPE",
"GROUPE_FOLDER_ID", "GROUPE_FOLDER_NAME") AS
select distinct "GROUPA_TYPE","GROUPA_FOLDER_ID","GROUPA_FOLDER_NAME",
"GROUPB_TYPE","GROUPB_FOLDER_ID","GROUPB_FOLDER_NAME","GROUPC_TYPE",
"GROUPC_FOLDER_ID","GROUPC_FOLDER_NAME","GROUPD_TYPE","GROUPD_FOLDER_ID",
"GROUPD_FOLDER_NAME","GROUPE_TYPE","GROUPE_FOLDER_ID","GROUPE_FOLDER_NAME"
from
(
select parent_4.*, product.ftype as groupe_type , customer_folder.customer_folder_id
as groupe_folder_id , customer_folder.folder_name as groupe_folder_name
from
customer_folder
left join product
on customer_folder.customer_folder_ID = product.folder_id
right join
(
select parent_3.*, product.ftype as groupd_type , customer_folder.customer_folder_id as
groupd_folder_id , customer_folder.folder_name as groupd_folder_name
from
customer_folder
left join product
on customer_folder.customer_folder_ID = product.folder_id
right join
(
select parent_2.*, product.ftype as groupc_type , customer_folder.customer_folder_id as groupc_folder_id , customer_folder.folder_name as groupc_folder_name
from
customer_folder
left join product
on customer_folder.customer_folder_ID = product.folder_id
right join
(
select parent_1.*, product.ftype as groupb_type ,
customer_folder.customer_folder_id
as groupb_folder_id, customer_folder.folder_name as groupb_folder_name
from
customer_folder
left join product
on customer_folder.customer_folder_ID = product.folder_id
right join
(
select product.ftype as groupa_type , customer_folder_id as
groupa_folder_id, folder_name as groupa_folder_name
from customer_folder
left join product
on customer_folder.customer_folder_ID = product.folder_id
where parent_folder_id = 1
) parent_1
on
customer_folder.parent_folder_id = parent_1.groupa_folder_id ) parent_2
on
customer_folder.parent_folder_id = parent_2.groupb_folder_id ) parent_3
on
customer_folder.parent_folder_id = parent_3.groupc_folder_id ) parent_4
on
customer_folder.parent_folder_id = parent_4.groupd_folder_id );

How do I remove duplicate results by looking for max date?

I know I have duplicate results from this query because the tables ReleaseHistory and IterationHistory have multiple records per ReleaseID and IterationID. I would like to only select the records with max date from dbo.ReleaseHistory and dbo.IterationHistory. How would I do that in this query? SQL SERVER 2008
SELECT dbo.Assignable.AssignableID AS ID,
dbo.EntityType.Abbreviation AS Entity,
dbo.General.Name, dbo.Assignable.Effort,
dbo.Assignable.EffortCompleted,
dbo.Assignable.EffortToDo,
dbo.EntityState.Name AS State,
dbo.ReleaseHistory.Name AS Release,
dbo.IterationHistory.Name AS Iteration,
dbo.General.CustomField3 AS [Scrum Team]
FROM dbo.Assignable INNER JOIN
dbo.General ON dbo.Assignable.AssignableID =
dbo.General.GeneralID INNER JOIN
dbo.EntityType ON dbo.General.EntityTypeID =
dbo.EntityType.EntityTypeID INNER JOIN
dbo.EntityState ON dbo.Assignable.EntityStateID =
dbo.EntityState.EntityStateID AND
dbo.EntityType.EntityTypeID =
dbo.EntityState.EntityTypeID INNER JOIN
dbo.ReleaseHistory ON dbo.Assignable.ReleaseID =
dbo.ReleaseHistory.ReleaseID INNER JOIN
dbo.IterationHistory ON
dbo.Assignable.IterationID =
dbo.IterationHistory.IterationID LEFT OUTER JOIN
dbo.CustomField ON dbo.General.CustomField3 =
dbo.CustomField.CustomFieldID
WHERE (dbo.Assignable.ProjectID = 4054)
GROUP BY dbo.Assignable.AssignableID,
dbo.EntityType.Abbreviation,
dbo.General.Name,
dbo.Assignable.Effort,
dbo.Assignable.EffortCompleted,
dbo.Assignable.EffortToDo,
dbo.EntityState.Name,
dbo.ReleaseHistory.Name,
dbo.IterationHistory.Name,
dbo.General.CustomField3
Brian,
I am amusing you are doing this in MS SQL and there will always be at least one record in ReleaseHistory and IterationHistory tables. If assumptions are correct then you can simply use CROSS APPLY to get top 1 record from both tables.
SELECT
dbo.Assignable.AssignableID AS ID ,
dbo.EntityType.Abbreviation AS Entity ,
dbo.General.Name ,
dbo.Assignable.Effort ,
dbo.Assignable.EffortCompleted ,
dbo.Assignable.EffortToDo ,
dbo.EntityState.Name AS State ,
Release ,
Iteration ,
dbo.General.CustomField3 AS [Scrum Team]
FROM
dbo.Assignable
INNER JOIN dbo.General ON dbo.Assignable.AssignableID = dbo.General.GeneralID
INNER JOIN dbo.EntityType ON dbo.General.EntityTypeID = dbo.EntityType.EntityTypeID
INNER JOIN dbo.EntityState ON dbo.Assignable.EntityStateID = dbo.EntityState.EntityStateID
AND dbo.EntityType.EntityTypeID = dbo.EntityState.EntityTypeID
CROSS APPLY( SELECT TOP 1 name Release FROM ReleaseHistory WHERE ReleaseID = Assignable.ReleaseID ORDER BY MaxDateColumn) a
CROSS APPLY( SELECT TOP 1 name Iteration FROM IterationHistory WHERE IterationID = Assignable.IterationID ORDER BY MaxDateColumn) b
LEFT OUTER JOIN dbo.CustomField ON dbo.General.CustomField3 = dbo.CustomField.CustomFieldID
WHERE
( dbo.Assignable.ProjectID = 4054 )
GROUP BY
dbo.Assignable.AssignableID ,
dbo.EntityType.Abbreviation ,
dbo.General.Name ,
dbo.Assignable.Effort ,
dbo.Assignable.EffortCompleted ,
dbo.Assignable.EffortToDo ,
dbo.EntityState.Name ,
dbo.ReleaseHistory.Name ,
dbo.IterationHistory.Name ,
dbo.General.CustomField3

sql group by with left join

fail statement:Error: ORA-00979: not a GROUP BY expression
select org_division.name , org_department.name , org_surveylog.division_code as divisionCode,org_surveylog.department_code as departmentCode , max(org_surveylog.actiondate) from org_surveylog
left join org_division on (org_surveylog.division_code= org_division.division_code and org_surveylog.SURVEY_NUM= org_division.survey_num)
left join org_department on (org_surveylog.department_code = org_department.department_code and org_surveylog.SURVEY_NUM = org_department.survey_num)
group by org_surveylog.division_code,org_surveylog.department_code
but below is ok
select org_surveylog.division_code as divisionCode,org_surveylog.department_code as departmentCode , max(org_surveylog.actiondate) from org_surveylog
left join org_division on (org_surveylog.division_code= org_division.division_code and org_surveylog.SURVEY_NUM= org_division.survey_num)
left join org_department on (org_surveylog.department_code = org_department.department_code and org_surveylog.SURVEY_NUM = org_department.survey_num)
group by org_surveylog.division_code,org_surveylog.department_code
how to use group by with left join when i need to show value of org_division.name , org_department.name ?
You need to change your GROUP BY to
group by org_division.name ,
org_department.name
org_surveylog.division_code,
org_surveylog.department_code
From Oracle Select Statements : Select Statement With GROUP BY Clause
SELECT <column_name>, <aggregating_operation>
FROM <table_name>
GROUP BY <column_name>;
You will notice that you need to include the non aggregated columns in the GROUP BY statement.