SQL Server 2012 Max Date in Subquery in a joined table - sql

I manage a state wide application and use Tableau to create visualizations of data.
I have been tasked with creating a visualization that show how much time is passing between contact entries and today (Case Note Dates). I know how to isolate the max case note date in the case note table:
Select
[Case_Master_ID],
[Case_Note_Date],
[Case_Note_Category_Desc],
[Case_Note_Summary_Narr]
From
buCase_Note
Where
Case_Note_Date = (Select MAX(Case_Note_Date)
From buCase_Note)
This query will show me that max case notes in the table from today. The issue is I need to show the max case note for all participants, not just the ones from today. The original query I have been using to view case notes is:
Select
vc.[_Case Master ID],
vc.[_Caseload Assignment Current],
vc.[_Participant Name],
vc.[Case Status],
vc.[Reporting Structure Level 4],
vc.[Reporting Structure Level 5],
vc.[Application Date],
vc.[Eligibility Date],
vc.[Eligibility Determination Extension Date],
vc.[Eligibility Extended To Date],
vc.[Days in Application],
cn.[Case_Note_Date],
cn.[Case_Note_Category_Desc],
cn.[Case_Note_Summary_Narr]
From
biVR_Cases vc
Left outer Join
buCase_Note cn ON cn.Case_Master_ID = vc.[_Case Master ID]
I need to keep biVR_Cases on the left to show all the open clients. Then I need to join in the case note table and for every participant, I want to show their max case note date. When I add this to the end of the above query:
Where cn.[Case_Note_Date] = (
Select
MAX(cn.Case_Note_Date)
From buCase_Note)
I get the following error is SSMS 2012:
An aggregate may not appear in the WHERE clause unless it is in a subquery contained in a HAVING clause or a select list, and the column being aggregated is an outer reference.
I am looking to retain the bi table on the left while successfully joining in the case note table and bringing in only the most recent case note per participant.
Adding details:
Of course,
Here is a sample of data I get when running the following query:
Select
vc.[_Case Master ID],
vc.[_Caseload Assignment Current],
vc.[_Participant Name],
cn.[Case_Note_Date],
From biVR_Cases vc
LEFT outer JOIN buCase_Note cn ON vc.[_Case Master ID] = cn.Case_Master_ID
_Caseload Assignment Current Test Participant Name Casenote Date
Test Counselor Participant A
September 29, 2010
September 23, 2010
August 30, 2010
June 30, 2010
June 1, 2010
The bi table contains participant information like name, application, case master ID, etc. The casenote table contains the case master ID as well hence the join. It also contains the dates each entry is created. So for the dataset above, I am trying to only bring in the most recent casenote for each participant. I only included 1 in the sample above, but we have over 15,000. Each participant will have many case notes. I am trying to grab the top casenote so I can calculate the date difference between the most recent case note and today for each participant. When I add :
Where cn.[Case_Note_Date] = (Select
top 1 [Case_Note_Date]
From buCase_Note
Order by 1 DESC))
OR
Where Case_Note_Date=(
Select
MAX(Case_Note_Date)
From buCase_Note)
It is only showing the top or max casenote for participants that had a casenote created today. Instead of showing the max casenote in the casenote table, I need the max casenote per participant. I hope that makes more sense.

You might try something like what I have included below. Without actual data, I do not know if it is efficient enough for you, but it should work. If you get a better answer, however, I would love to know it.
Select vc.[_Case Master ID],
vc.[_Caseload Assignment Current],
vc.[_Participant Name],
vc.[Case Status],
vc.[Reporting Structure Level 4],
vc.[Reporting Structure Level 5],
vc.[Application Date],
vc.[Eligibility Date],
vc.[Eligibility Determination Extension Date],
vc.[Eligibility Extended To Date],
vc.[Days in Application],
cn.[Case_Note_Date],
cn.[Case_Note_Category_Desc],
cn.[Case_Note_Summary_Narr]
From biVR_Cases vc
LEFT outer JOIN
(SELECT Case_Master_ID, Case_Note_Date, Case_Note_Category_Desc, Case_Note_Summar_Narr,
ROW_NUMBER() OVER (PARTITION BY Case_Master_ID ORDER BY Case_Note_Date DESC) as RowNum FROM buCase_Note) cn
ON cn.Case_Master_ID = vc.[_Case Master ID] AND cn.RowNum=1

Remove the cn. from the MAX(cn.Case_Note_Date) row. You don't want to reference column from the main query. You just want to select a Case_Note_Date from buCase_Note.
So the whole query will be
Select
vc.[_Case Master ID],
vc.[_Caseload Assignment Current],
vc.[_Participant Name],
vc.[Case Status],
vc.[Reporting Structure Level 4],
vc.[Reporting Structure Level 5],
vc.[Application Date],
vc.[Eligibility Date],
vc.[Eligibility Determination Extension Date],
vc.[Eligibility Extended To Date],
vc.[Days in Application],
cn.[Case_Note_Date],
cn.[Case_Note_Category_Desc],
cn.[Case_Note_Summary_Narr]
From biVR_Cases vc
LEFT outer JOIN buCase_Note cn ON cn.Case_Master_ID = vc.[_Case Master ID]
Where cn.[Case_Note_Date] = (Select
MAX(Case_Note_Date)
From buCase_Note)

Related

Optimizing Access Query with Multiple sub-queries

I have a table of data that contains baseline project information, called ADMIN_WORK. I have a separate table that contains various attributes related to each project listed in ADMIN_WORK called WR_ATTRIBUTE. The structure of WR_ATTRIBUTE is such that each project has about 300 attributes (300 rows in the table) each with a unique name associated with the project number. I need to pull approximately 15 of these attributes into a final table.
I built a query with a number of sub-queries, but it takes multiple hours to run. The code below represents pulling a single attribute (called Circuit) from WR_ATTRIBUTE for all projects.
SELECT ADMIN_WORK.WR_NO AS [WR Number],
ADMIN_WORK.PREMISE_ID AS [Premise ID],
AttributeCircuit.Circuit
FROM ADMIN_WORK INNER JOIN
(SELECT ADMIN_WORK.WR_NO AS [WR Number], WR_ATTRIBUTE.ATTRIBUTE_VALUE AS Circuit
FROM ADMIN_WORK INNER JOIN
WR_ATTRIBUTE ON ADMIN_WORK.WR_NO = WR_ATTRIBUTE.WR_NO
WHERE (((WR_ATTRIBUTE.WR_ATTRIBUTE_CODE)="Circuit") AND ((ADMIN_WORK.WR_TYPE_CODE)="ACNEM"))
) AS AttributeCircuit
ON ADMIN_WORK.WR_NO = [AttributeCircuit].[WR Number]);
My final query has about 14 more of these subqueries similarly implemented, each with a different WR_ATTRIBUTE_CODE.
My final table is generated accurately, but it is extremely slow. I am wondering if there is a better way of structuring my query.
You probably just want conditional aggregation:
SELECT w.WR_NO AS [WR Number],
w.PREMISE_ID AS [Premise ID],
a.Circuit
FROM ADMIN_WORK as INNER JOIN
(SELECT a.WR_NO AS [WR Number],
MAX(IIF(a.WR_ATTRIBUTE_CODE)="Circuit" a.ATTRIBUTE_VALUE, NULL) AS Circuit ,
. . .
FROM WR_ATTRIBUTE as a
GROUP BY WR_NO
) as a
ON w.WR_NO = a.WR_NO ;

Multiple joins to create a cross tab

I have two queries I want to join so I can get the percentages from each department of completed work orders but not sure how to go about it. I know I want a join and a crosstab query so I can display the results in a report.
The first query calculates the numerator,
SELECT
Count(MaximoReport.WorkOrder) AS CountOfWorkOrder,
MaximoReport.[Assigned Owner Group]
FROM MaximoReport
WHERE (
((MaximoReport.WorkType) In ("PMINS","PMOR","PMPDM","PMREG","PMRT"))
AND ((MaximoReport.Status) Like "*COMP")
AND ((MaximoReport.[Target Start])>=DateAdd("h",-1,[Enter the start date])
AND (MaximoReport.[Target Start])<DateAdd("h",23,[Enter the end date]))
AND ((MaximoReport.ActualLaborHours)<>"00:00")
AND ((MaximoReport.ActualStartDate)>=DateAdd("h",-11.8,[Enter the start date])
AND (MaximoReport.ActualStartDate)<DateAdd("h",23,[Enter the end date]))
)
GROUP BY MaximoReport.[Assigned Owner Group];
While the second query calculates the denominator:
SELECT
Count(MaximoReport.WorkOrder) AS CountOfWorkOrder,
MaximoReport.[Assigned Owner Group]
FROM MaximoReport
WHERE (
((MaximoReport.WorkType) In ("PMINS","PMOR","PMPDM","PMREG","PMRT"))
AND ((MaximoReport.Status)<>"CAN")
AND ((MaximoReport.[Target Start])>=DateAdd("h",-11.8,[Enter the start date])
AND (MaximoReport.[Target Start])<DateAdd("h",23,[Enter the end date])))
GROUP BY MaximoReport.[Assigned Owner Group];
Please advise how I can join the two queries to get the percentages of the departments and then do a crosstab query.
If there is a better way of doing this please also let me know.

Need MS Access Form Field to automatically Calculate and Allocate Costs based on given Parameters

Below is my mock database that I am using. I have four different tables: Tbl_MainDatabase, Tbl_InsuranceCoverage, Tbl_MatterDetail, and Tbl_PaymentProcessing.
What I want -
I want my form to determine the remaining Retention Limit (i.e., Retention Limit for the applicable policy - sum of invoices for the same Claim Number )
According to the mock database, the required answer should be [ $2500 - (300+700+355)] as highlighted for your convenience
What I tried
I used the help of Graphical representation through the following query:
SELECT [Claim Number], Sum([Net Invoice Amount])
FROM [PaymentProcessing]
GROUP BY [Claim Number]
This method works to show me how much I spent per claim number so far in the form of a graph. However I want to display the remaining amount.
Any Help is appreciated :)
I am one month old at using Access. But I am trying my best to learn
Thank you in advance!
SELECT
IC.[Retention Limit]-SUM([Net Invoice Amt]) AS Remaining, MD.[Claim Number], IC.[Retention Limit], IC.InsuranceID
FROM tbl_InsuranceCoverage IC
INNER JOIN tbl_MatterDetail MD ON ic.InsuranceID = MD.Policy
INNER JOIN tbl_PaymentProcessing PP ON MD.MatterDetailID=pp.MatterDetailID AND MD.[Claim Number]=pp.[Claim Number]
GROUP BY MD.[Claim Number], IC.[Retention Limit], IC.InsuranceID
See if this works. Havent tested it but seems simple. You can remove the extra columns, but this will hlep you understand joins a bit
For All the New users The above code by #Doug Coats works perfectly.
Make Sure All the Foreign Key and Primary Keys is linked in the Relationship Property. ( One of the way To do this in the Query is - Right click on the Query and select Design View --> Right click again on the grey space and Select Show all Tables Now Drag your Primary Key of the table and drop at the foreign Key on the other table --> This will create a relationship between both for the Query Purpose.
This will also Prevent Data from Duplication in the query then use a similar code as described by Doug Coats in the above comment in the SQL View
SELECT [Insurance Coverage].[Retention Unit]-Sum([Net Invoice Amount]) AS Remaining, [Matter Detail].[Claim Number], [Insurance Coverage].[Retention Unit], [Matter Detail].Policy
FROM (([Main Database] INNER JOIN [Matter Detail] ON [Main Database].[Database ID] = [Matter Detail].[Short Name]) INNER JOIN [Payment Processing] ON ([Matter Detail].[Matter Detail ID] = [Payment Processing].[Matter Detail ID]) AND ([Main Database].[Database ID] = [Payment Processing].[Short Name])) INNER JOIN [Insurance Coverage] ON [Matter Detail].Policy = [Insurance Coverage].[Insurance ID]
GROUP BY [Matter Detail].[Claim Number], [Insurance Coverage].[Retention Unit], [Matter Detail].Policy;
You can then display this query in the form - I am still evaluating best way to display this query probably in a Combo Box (Not sure if any other controls has a row source)
Thank you

Aggregating Child Records at the Parent Level in Access 2010

The link above will provide an excel sheet with some sample data from both the parent and child table with expected result from the query.
Alright this should be simple but I just can't wrap my head around this for some reason. Pretty much, I have a parent table that is linked to a child table. I want to pull up few of the fields from the child table and merge it with the parent fields. I want to create a view of sort in Access.
The parent record can have multiple child records (1 - many relationship). I want to only pull up one record from the child and merge with the parent. The parent table is called Tank and the child table is Tank_Inspections. The IF statement you see below is a conditional statement that helps in determining which Out of Compliance date I should be pulling up. The issue I'm having is that the Out of Compliance date is tied to inspection type. A Tank can have multiple different inspection types. They query below merges the inspection out of compliance date with few of the tank (parent) fields. However, I want to be able to add more of the child fields (in addition to the inspection out of compliance date) but I can't do that without adding those fields to the group by clause as well. If I do that, then I won't get the right amount of records.
As you can see, the left join is getting all of the records from the parent table which is what I need. If I add any more child table fields to the query, I'll also need to add them to the group by clause and then I'll get more records than what's in the parent table. Essentially, I need to only get the records from the parent table, and then merge child fields in. I may be missing few sub queries... Any suggestions? This is what I have so far and I'm getting the right amount of records. But adding more child fields to the select statement will add more rows than i need...
SELECT parent.tankid, IIf(Min(Nz(child.[tank inspection out of compliance date], #1/1/1901#)) <> #1/1/1901#, Min(child.[tank inspection out of compliance date]), IIf(Min(Nz(child.[tank inspection out of compliance date],#1/1/1901#)) = #1/1/1901# And Max(child.[tank inspection out of compliance date])>Date(), NULL, Min(child.[tank inspection out of compliance date]))) AS [Tank Inspection Out of Compliance Date]
FROM
tank as parent
LEFT JOIN
(
SELECT * FROM tank_inspections WHERE tank_inspections.[actual inspection date] is null
) AS child ON parent.tankid = child.tankid GROUP BY parent.tankid
I was able to modify Parfait suggested query below to come up with this:
SELECT
Site.[Manager] AS PM, Site.[DLA Site Code], Tank.[Name] AS [Name], Tank.[Local Name],
Tank.RPID, Tank.[Fac Num], Tank.[Status], Tank.[Type], Tank.[Capacity], Tank.[Current Prod], IIf(main.[Inspection Out of Compliance Date]<Date() AND NOT IsNull(main.[Inspection Out of Compliance Date]), 'Out of Compliance',
IIf(isnull(main.[Inspection Out of Compliance Date]) OR main.[Inspection Out of Compliance Date]=#1/1/1901#,'Unknown Compliance Status')) AS [Compliance Status], Tank.[EA], Site.Serv, Site.[Name], Tank.Comments, main.[Type], main.[Inspection Out of Compliance Date], main.[Planned Prog Date], main.[Prog Date], main.[Prog Year], main.[Planned Inspection Date], IIf(main.[Inspection Out of Compliance Date]<DateAdd('m',12,Date()) And main.[Prog Date] Is Null,'Action Required') AS [Inspection Planning Action Required], main.[Inspection Comments], tank.TankID, main.inspectionid
FROM
Site INNER JOIN
(
(
(
SELECT ti.tankid, ti.inspectionid, ti.[Type], ti.[Inspection Out of Compliance Date], ti.[Planned Prog Date], ti.[Prog Date], ti.[Prog Year], ti.[Planned Inspection Date], ti.[Inspection Comments] FROM Tank_Inspections AS ti) AS main INNER JOIN Tank ON main.TankID = Tank.TankID) INNER JOIN
(
SELECT [TankID], dlookup("InspectionID", "Tank_Inspections", "[Tank Inspection Out of Compliance Date] " & IIf(Min(Nz([inspection out of compliance date], #1/1/1901#)) <> #1/1/1901#, "= #" & Min([inspection out of compliance date]) & "#", IIf(Min(Nz([inspection out of compliance date],#1/1/1901#)) = #1/1/1901# And Max([inspection out of compliance date])>Date(), "IS NULL", IIF(Min(Nz([inspection out of compliance date],#1/1/1901#)) = #1/1/1901# And Max([inspection out of compliance date])<Date(), "= #" & Min([inspection out of compliance date]) & "#", "IS NULL"))) & " AND TankID = " & TankID & " AND [Actual Inspection Date] is null") AS MinInspectionID FROM Tank_Inspections WHERE [Actual Inspection Date] is null GROUP BY [TankID]
)AS DT ON
(
main.InspectionID = Cint(DT.MinInspectionID)
) AND (main.TankID = DT.TankID)
) ON Site.SiteID = Tank.SiteID
WHERE IIf(main.[Inspection Out of Compliance Date]<Date() And NOT IsNull(main.[Inspection Out of Compliance Date]),'Out of Compliance',IIf(isnull(main.[Inspection Out of Compliance Date]) OR main.[Inspection Out of Compliance Date]=#1/1/1901#,'Unknown Compliance Status'));
I'm close with this query, however, I'm missing a few records. The parent records don't have some of the child records. For example, some of the tank records don't have any inspection records so it's not being pulled. I need to do a left join but can't seem to figure it out with this query. Everything I try doesn't seem to work. Suggestion?
Consider the following query that uses a derived table and joins the unit level parent (Tank) to aggregated child (TankInspections). You can save the derived table as a separate stored query and just replace entire select statement and alias (DT) with query name. I include more aggregates than needed for you to check calculated columns:
SELECT Tanks.*, main.*, DT.MaxInspectionID, DT.MaxInspectionOrComplianceDate
FROM
(TankInspections main
INNER JOIN Tanks ON Tanks.TankID = main.TankID)
INNER JOIN
(
SELECT [TankID],
Max(InspectionID) As MaxInspectionID,
Min([Planned Inspection Date]) As MinInspection,
Max([Planned Inspection Date]) As MaxInspection,
Min([Inspection Out of Compliance Date]) As MinCompliance,
Max([Inspection Out of Compliance Date]) As MaxCompliance,
Max(IIF(([Planned Inspection Date]) Is Null,
IIF(ISNULL([Inspection Out of Compliance Date]),
NULL,
[Inspection Out of Compliance Date]),
[Planned Inspection Date])) As MaxInspectionOrComplianceDate
FROM TankInspections
GROUP BY [TankID]
) As DT
ON main.TankID = DT.TankID
AND main.InspectionID = DT.MaxInspectionID;

SQL query ordering wrong, not sure why

SELECT a.[Evaluation Number], a.[CSO Name], a.service
, a.[Date of call], a.[Name of Monitor]
, a.[Date Sheet Completed]
FROM [KD call monitoring] AS a
WHERE a.[Evaluation Number]
IN (SELECT TOP 1 [Evaluation Number]
FROM [KD call monitoring] b
WHERE b.[CSO Name] = a.[CSO Name]
AND b.[Date of Call] =
(SELECT MAX([date of call])
FROM [KD call monitoring]
WHERE [cso name] = a.[CSO Name])
ORDER BY [Evaluation Number]);
this is the code i have on my call evaluation database at work, it is ordering the entries so i know which employee has not had their calls monitored for a while. however it orders fine from 31st jan up until the end of febuary (about halfway down the list) then just places random peoples entries before settling down and giving me the most recent person and entry that has been evaluated.
this list only needs to show one entry per person - the latest one.
im not sure if its messing up because of the leap year or something but i have no idea how to fix it!
im using ACCESS XP. and i would attach an image however im a new user so not allowed!
You don't seem to have an ORDER BY on your outer-most query so the final resultset will not be ordered.