Query 1 results in 87 rows:
SELECT
MIN(LEFT(Date_Last_Updated, 4)) AS Year_of_Transfer,
MIN(RIGHT(LEFT(Date_Last_Updated, 6), 2)) AS Month_of_Transfer,
MIN(RIGHT(LEFT(Date_Last_Updated, 8), 2)) AS Day_of_Transfer,
CRS, Loan_Code,
MIN(Date_Last_Updated) AS Min_Date_Last_Updated
FROM
dbo.Transfer_Final_Accounts_CO_SH
WHERE
(LEFT(Date_Last_Updated, 4) >= '2016')
AND (Subcategory = 'Transfer to Workout')
GROUP BY
CRS, Loan_Code
ORDER BY
Loan_Code
Query 2 results in 3400000 rows:
SELECT
Date_Last_Updated,
SUM(NPL_Amount_Last_Quarter) AS NPL_Amount_Last_Quarter,
Loan_Code,
SUM([Total_Balance_€]) AS Total_Balance,
SUM(On_Balance_Amount_Last_Quarter) AS On_Balance_Last_Q,
SUM([Off_Balance_Amount_€]) AS Off_Balance_Last_Q, CRS,
[On_Balance_Amount_€], [Off_Balance_Amount_€], [Total_Balance_€],
NPL_Amount_Last_Quarter AS NPL_Amount_Last_Q,
[NPL_Amount_€], On_Balance_Amount_Last_Quarter,
Material_Bucket, Material_Bucket_Last_Quarter
FROM
dbo.Transfer_Final_Accounts_COM_WORK
GROUP BY
CRS, Date_Last_Updated, Loan_Code, [On_Balance_Amount_€],
[Off_Balance_Amount_€], [Total_Balance_€], NPL_Amount_Last_Quarter,
[NPL_Amount_€], On_Balance_Amount_Last_Quarter, Material_Bucket,
Material_Bucket_Last_Quarter
Query 3 connects the 2 above and results in 0 rows:
SELECT
dbo.Transfer_to_Workout_Total_Balances.Total_Balance,
dbo.Transfer_to_Workout_Total_Balances.On_Balance_Last_Q,
dbo.Transfer_to_Workout_Total_Balances.Off_Balance_Last_Q,
dbo.Transfer_to_Workout_Total_Balances.NPL_Amount_Last_Quarter,
dbo.Transfer_to_workout_min_dates.Year_of_Transfer,
dbo.Transfer_to_workout_min_dates.Month_of_Transfer,
dbo.Transfer_to_workout_min_dates.Day_of_Transfer,
dbo.Transfer_to_workout_min_dates.CRS AS Expr1,
dbo.Transfer_to_workout_min_dates.Loan_Code AS Expr2,
dbo.Transfer_to_workout_min_dates.Min_Date_Last_Updated,
dbo.Transfer_to_Workout_Total_Balances.[On_Balance_Amount_€],
dbo.Transfer_to_Workout_Total_Balances.[Off_Balance_Amount_€],
dbo.Transfer_to_Workout_Total_Balances.[Total_Balance_€],
dbo.Transfer_to_Workout_Total_Balances.[NPL_Amount_€],
dbo.Transfer_to_Workout_Total_Balances.NPL_Amount_Last_Q,
dbo.Transfer_to_Workout_Total_Balances.On_Balance_Amount_Last_Quarter,
dbo.Transfer_to_Workout_Total_Balances.Material_Bucket,
dbo.Transfer_to_Workout_Total_Balances.Material_Bucket_Last_Quarter
FROM
dbo.Transfer_to_workout_min_dates
INNER JOIN
dbo.Transfer_to_Workout_Total_Balances ON dbo.Transfer_to_workout_min_dates.Loan_Code = dbo.Transfer_to_Workout_Total_Balances.Loan_Code
AND dbo.Transfer_to_workout_min_dates.Min_Date_Last_Updated = dbo.Transfer_to_Workout_Total_Balances.Date_Last_Updated
What is wrong with the connections why am I not taking the results from the above?
When your query 3 doesn't return a row but the underlaying tables dbo.Transfer_to_workout_min_dates and dbo.Transfer_to_Workout_Total_Balances contain data, then most likely the join condition (ON) is not met for any entries in those tables.
Try to remove one of the terms (I would start with the Min_Date_Last_Updated one). It should change something. Then check in the result the both fields. You'll see that they differ and so are never equal.
Related
How do you use LIKE with ORDER BY CASE in SQL? Or in other words, how do you do a partial text search for the following:
ORDER BY CASE [Column Name] WHEN [value partial text%]
Problem: I'm referencing a table (named "Personnel") with column (titled "Rank"), which lists each employee's job title followed by their level of certification (many variables). I would like to order the SQL query results by job title, ignoring the certification level that follows title name.
Example values in Personnel.Rank Column:
Captain Paramedic
Captain Intermediate
Captain EMT
Lieutenant Paramedic
Lieutenant Intermediate
Lieutenant EMT
Apparatus Operator Paramedic
Firefighter EMT
Firefighter AEMT
This works, but I don't want to list every variable as a WHEN clause:
SELECT
p.Rank
FROM Personnel p
ORDER BY
CASE p.Rank
WHEN 'Captain Paramedic' THEN 1
WHEN 'Captain EMT' THEN 1
WHEN 'Lieutenant Paramedic' THEN 2
WHEN 'Lieutenant EMT' THEN 2
ELSE 3
END
I would like to know how to do something like this instead:
SELECT
p.Rank
FROM Personnel p
ORDER BY
CASE p.Rank
WHEN LIKE 'Captain%' THEN 1
WHEN LIKE 'Lieutenant%' THEN 2
ELSE 3
END
Thoughts?
LIKE operator is not permitted with ORDER BY CASE [column name] WHEN statement
It is possible you can just fix up the syntax and still use your case statement. Untested but the syntax I would expect is:
SELECT
p.Rank
FROM Personnel p
ORDER BY
CASE
WHEN p.Rank LIKE 'Captain%' THEN 1
WHEN p.Rank LIKE 'Lieutenant%' THEN 2
ELSE 3
END
A more general purpose solution would be to use a reference or lookup table to get your order by values. Here is an example written in PSEUDOSQL just to show the idea. In real life, you can create your table or use a temp table or a CTE. The pro here is you can maintain this a little more cleanly (in your ref table - or SortOrder can be a field right in your Personnel table). The con here is you have "promoted" a simple ordering problem into something more permanent and if this is only an ad hoc need for an ad hoc query then it might be overkill.
create temporary table SortOrder (Rank, SortOrder)
insert into SortOrder
values
('Captain Paramedic', 10),
('Captain Intermediate', 10),
('Captain EMT', 10),
('Lieutenant Paramedic', 20),
('Lieutenant Intermediate', 20),
('Lieutenant EMT', 20),
('Apparatus Operator Paramedic', 30),
('Firefighter EMT', 40),
('Firefighter AEMT', 40)
SELECT
p.Rank
FROM
Personnel p
LEFT JOIN SortOrder s
ON p.Rank = s.Rank
ORDER BY
COALESCE(s.SortOrder, 100)
I need to get a state level count on number of services. For the purposes of this I only have two services. The first column is the states, the second column is the first services and the third column is the second service. What I am struggling with is to have the second and third column show up on the results in one query. Here is my code:
SELECT Distinct allstates.Name, count (data.StateName) as CareCase_Management_Services, count(data.StateName) Caregiver_Support_Services
From
(select distinct Name from USstate) allstates
Left Join
Client2017 data
on
allstates.Name = data.StateName and
data.FiscalYear = 2017 and
data.SrvstartCareCaseMgmtCode NOT IN('999','', '998') and
data.SrvstartCaregiverSuppCode NOT IN('999','', '998')
GROUP BY allstates.Name
ORDER BY allstates.Name ASC
I understand that you are looking to compute, for each state, the count of services that match certain criteria. There are two types of services, stored in two different columns.
If so, your query could be simplified using conditional aggregation :
SELECT
allstates.Name,
SUM(CASE WHEN c.SrvstartCareCaseMgmtCode NOT IN ('999', '', '998') THEN 1 ELSE 0 END) CareCase_Management_Services,
SUM(CASE WHEN c.SrvstartCaregiverSuppCode NOT IN ('999', '', '998') THEN 1 ELSE 0 END) Caregiver_Support_Services
FROM
(SELECT DISTINCT Name FROM USstate) s
LEFT JOIN Client2017 c ON s.Name = c.StateName AND c.FiscalYear = 2017
GROUP BY allstates.Name
With this technique, each service is counted according to its own logic ; when conditions are met, the record is counted in (1 is added to the SUM()), else it is ignored (+ 0).
NB : do you really have duplicated state names in USstate ? if no, you can replace subquery (SELECT DISTINCT Name FROM USstate) s with just USstate
I wanted to get clarity on how the HAVING component in an SQL statement works, particularly with a SQL statement that has multiple joins. Consider the following SQL select statement:
SELECT
p.id,
p.first_name as [First Name],
p.last_name as [Last Name]
FROM
( [tbl_person] as p
INNER JOIN [tbl_person_languages] as pl
ON [p].[id] = [pl].[person_id])
INNER JOIN [tbl_person_crossCuttingSkills] As ccp
ON [p].[id] = [ccp].[person_id]
WHERE
cint(pl.language_id) in (12,14) AND
cint(ccp.skill_id) in (55)
GROUP BY
p.id,
p.first_name,
p.last_name
HAVING
count(pl.language_id) =2 AND
count(ccp.skill_id) = 1
I want to pull out records, from tbl_person, where a record has all of the WHERE requirements. For example: I want to select all users where they speak a languages Italian (with ID 12) and Spanish (ID 15) AND have a skill of cooking (55). They need to have all requirements, not just one or more. I was under the assumption this is where you would use GROUP BY and HAVING. With the HAVING:
count(pl.language_id) =2
I use count = 2 because there are two options in the language WHERE clause (12 and 14)
And I use
count(ccp.skill_id) = 1
Because there is one value in the WHERE clause (55).
Is this the correct way to be doing this? For some reason, this returns no records (I have one record in my DB of a person who fits these requirements exactly). But, if I change my HAVING to:
count(pl.language_id) =2 AND
count(ccp.skill_id) = 2
It works fine. Why is this? Are my assumptions of how this works incorrect or is there something else going on?
Remember what count() does . . . it counts non-NULL values. So, you are counting two non-NULL values then the counts are the same.
In most dialects of SQL, you can fix this by doing:
HAVING count(distinct pl.language_id) = 2 AND count(distinct ccp.skill_id) = 1
But that doesn't work in MS Access, because MS Access does not support COUNT(DISTINCT).
So, you can be more verbose. In your case:
HAVING SUM(iif(cint(pl.language_id) = 12, 1, 0)) > 0 AND
SUM(iif(cint(pl.language_id) = 14, 1, 0)) > 0 AND
SUM(iif(cint(ccp.skill_id) = 55, 1, 0)) > 0
I'm sorry this HAVING clause is not simpler. You could switch to another database (such as SQL Server Express) that more closely aligns with ANSI functionality.
is there anyway to get the following results from query without joining the same table three times (or) without reading the same "wordlocation" table three times (or more if there are more words)? If there are three or more words, it takes about over a minute for the results to be returned.
Currently "wordlocation" table has three rows being ("bookid","wordid","location") and it currently has 917802 rows.
What I am trying to do is
retrieve the "bookid" that contains all the words specified in the query by "wordid".
sum word count of all words (from the query) from each book
minimum values of each word location, e.g. (min(w0.location), min (w1.location)
I have tried commenting out count(w0.wordid) and min(location) calculations to see whether they are affecting the performance but this is not the case. Joining the same table multiple time was the case.
(this is the same code as the above image)
select
w0.bookid,
count(w0.wordid) as wcount,
abs(min(w0.location) + min(w1.location) + min(w2.location)) as wordlocation,
(abs(min(w0.location) - min(w1.location)) + abs(min(w1.location) - min(w2.location))) as distance
from
wordlocation as w0
inner join
wordlocation as w1 on w0.bookid = w1.bookid
join
wordlocation as w2 on w1.bookid = w2.bookid
where
w0.wordid =3
and
w1.wordid =52
and
w2.wordid =42
group by w0.bookid
order by wcount desc;
This is the result that I am looking for, and which I got from running the above query, but it takes too long if I specify more than 3 words, e.g. (w0 = 3, w1 = 52 , w2 = 42, w3 = 71)
Try this query
SELECT bookid,
ABS(L3+L52+L42) as wordlocation,
ABS(L3-L52)+ABS(L52-L42) as distance
FROM
(SELECT bookid, wordid, CASE WHEN wordid=3 THEN min(location) ELSE 0 END L3,
CASE WHEN wordid=52 THEN min(location) ELSE 0 END L52,
CASE WHEN wordid=42 THEN min(location) ELSE 0 END L42
FROM wordlocation WL
WHERE wordid in (3,52,42)
GROUP BY bookid, wordid) T
GROUP BY bookid
You may also need to create index on wordid
I have the following table:
I am trying to create an SQL query that returns a table that returns three fields:
Year (ActionDate), Count of Built (actiontype = 12), Count of Lost (actiontype = a few different ones)
Bascially, ActionType is a lookup code. So, I'd get back something like:
YEAR CountofBuilt CountofLost
1905 30 18
1929 12 99
1940 60 1
etc....
I figured this would take two SELECT statements put together with a UNION.
I tried the following below but it only spits back two columns (year and countbuilt). My countLost field doesn't appear
My sql currently (MS Access):
SELECT tblHist.ActionDate, Count(tblHist.ActionDate) as countBuilt
FROM ...
WHERE ((tblHist.ActionType)=12)
GROUP BY tblHist.ActionDate
UNION
SELECT tblHist.ActionDate, Count(tblHist.ActionDate) as countLost
FROM ...
WHERE (((tblHist.ActionType)<>2) AND
((tblHist.ActionType)<>3))
GROUP BY tblHist.ActionDate;
Use:
SELECT h.actiondate,
SUM(IIF(h.actiontype = 12, 1, 0)) AS numBuilt,
SUM(IIF(h.actiontype NOT IN (2,3), 1, 0)) AS numLost
FROM tblHist h
GROUP BY h.actiondate
You should not use UNION for such queries. There are many ways to do what you want, for example
Updated to fit access syntax
SELECT tblHist.ActionDate,
COUNT(SWITCH(tblHist.ActionType = 12,1)) as countBuilt,
COUNT(SWITCH(tblHist.ActionType <>1 OR tblHist.ActionType <>2 OR ...,1)) as countLost
FROM ..
WHERE ....
GROUP BY tblHist.ActionDate