SQL query with multiple where clause - sql

I'm trying to write a query for a dataset in SSRS. I have a joining table called RequestSchools which links to three other tables:
Schools
Placing Request
RequestSchoolType
I want to get the name of the RequestedSchool (RequestedSchoolTypeId = 3)
I also want the name of the CatchmentSchool (RequestSchoolTypeId = 1)
I've attached an image of the SQL query that I can get working with the requested school. I want the catchment school as well. Grateful for any help with this.
SELECT
pr.PlacingRequestId, s.Name AS RequestedSchool
FROM
PlacingRequests AS pr
INNER JOIN
RequestSchools AS rs ON rs.PlacingRequestId = pr.PlacingRequestId
JOIN
Schools s ON s.SchoolId = rs.SchoolId
WHERE
rs.RequestSchoolTypeId = 3

I'm not 100% sure this is correct, as we can't see the schema, source data or a full example of the desired output, but I think this might be it:
SELECT
pr.PlacingRequestId,
s.Name as RequestedSchool,
cs.Name as CatchmentSchool
FROM
PlacingRequests AS pr
INNER JOIN RequestSchools AS rs
ON rs.PlacingRequestId = pr.PlacingRequestId
INNER JOIN Schools s
on s.SchoolId = rs.SchoolId
AND rs.RequestSchoolTypeId = 3 -- requested school
INNER JOIN Schools cs
on cs.SchoolId = rs.SchoolId
AND rs.RequestSchoolTypeId = 1 -- catchment school
Happy to update if it's not what you meant, and you can clarify the question as indicated.

According what I understand about your requirement, you will be needing multiple joins and not another AND condition in the where clause. So we can omit the where here and join the requestschools with schools one more time for CatchmentSchool as we have done it once already for Requestedschool. Only difference is we are using the requestedtypeid and catchmenttypeid values while joining.
Select
pr.PlacingRequestId,
rs.Name as RequestedSchool
cs.Name as CatchmentSchool
FROM
PlacingRequests AS pr
INNER JOIN RequestSchools AS rrs
ON rrs.PlacingRequestId = pr.PlacingRequestId
and rrs.RequestSchoolTypeId = 3
JOIN Schools rs
on rs.SchoolId = rrs.SchoolId
INNER JOIN RequestSchools AS crs
ON crs.PlacingRequestId = pr.PlacingRequestId
and crs.RequestSchoolTypeId = 1
JOIN Schools cs
on cs.SchoolId = crs.SchoolId
Hope this helps...

The best way to do this is with a CASE function, but I don't know which RDBMS you are using so here is the brute force approach: just run your query as two sub-queries, each specifying a different type ID and then join them. It would be something like this:
SELECT DISTINCT catch.placingrequestid, catch.catchmentschool, requested.requestedschool
FROM
(SELECT pr.placingrequestid, s.nam as catchmentschool
FROM (PlacingRequest pr
INNER JOIN RequestSchools rs ON pr.placingrequestid = rs.placingrequestid)
INNER JOIN School s ON rs.schoolid = s.schoolid
WHERE rs.requestschooltypeid = 1) catch
INNER JOIN
(SELECT pr.placingrequestid, s.nam as requestedschool
FROM (PlacingRequest pr
INNER JOIN RequestSchools rs ON pr.placingrequestid = rs.placingrequestid)
INNER JOIN School s ON rs.schoolid = s.schoolid
WHERE rs.requestschooltypeid = 3) requested
ON catch.placingrequestid = requested.placingrequestid

Related

Access Query - Group by and Max

I have been working on this for a few hours now and just can not figure it out.
How would I go about sorting this query by enco_id and only having the max of each clpr_id show up. for example:
Here is my MSAccess Sql Code
SELECT dbo_Client.med_rec_no, dbo_Encounter.episode_number, dbo_client_program.enco_id, dbo_client_program.clpr_id, dbo_client_program.prle_id, dbo_PROGRAM_LEVEL.prle_name, dbo_Client.fname, dbo_Client.lname, dbo_DISCHARGE_STATUS.dist_name, DS2.dist_name
FROM (((((dbo_Client INNER JOIN dbo_Encounter ON dbo_Client.client_id = dbo_Encounter.client_id) INNER JOIN dbo_Episode_info ON dbo_Encounter.enco_id = dbo_Episode_info.enco_id) INNER JOIN dbo_DISCHARGE_STATUS ON dbo_Episode_info.dist_id = dbo_DISCHARGE_STATUS.dist_id) INNER JOIN dbo_client_program ON dbo_Encounter.enco_id = dbo_client_program.enco_id) INNER JOIN dbo_DISCHARGE_STATUS AS DS2 ON dbo_client_program.dist_id = DS2.dist_id) INNER JOIN dbo_PROGRAM_LEVEL ON dbo_client_program.prle_id = dbo_PROGRAM_LEVEL.prle_id;
Also here is what my query looks like
EDIT:
This is the code I am trying to use now and it still is not working
SELECT dbo_Client.client_id, dbo_Client.med_rec_no, dbo_Encounter.episode_number, dbo_Encounter.start_date, dbo_Encounter.end_date, dbo_client_program.clpr_id, dbo_client_program.enco_id, dbo_PROGRAM_LEVEL.prle_name, dbo_Client.fname, dbo_Client.lname, dbo_DISCHARGE_STATUS.dist_name, DS2.dist_name
FROM (((((dbo_Client INNER JOIN dbo_Encounter ON dbo_Client.client_id = dbo_Encounter.client_id) INNER JOIN dbo_Episode_info ON dbo_Encounter.enco_id = dbo_Episode_info.enco_id) INNER JOIN dbo_DISCHARGE_STATUS ON dbo_Episode_info.dist_id = dbo_DISCHARGE_STATUS.dist_id) INNER JOIN dbo_client_program ON dbo_Encounter.enco_id = dbo_client_program.enco_id) INNER JOIN dbo_DISCHARGE_STATUS AS DS2 ON dbo_client_program.dist_id = DS2.dist_id) INNER JOIN dbo_PROGRAM_LEVEL ON dbo_client_program.prle_id = dbo_PROGRAM_LEVEL.prle_id
WHERE dbo_client_program.clpr_id IN
(SELECT TOP 1 clpr_id FROM dbo_client_program as New
WHERE New.clpr_id = dbo_client_program.clpr_id
ORDER by dbo_client_program.clpr_id DESC) AND (dbo_DISCHARGE_STATUS.dist_name <> DS2.dist_name) AND dbo_Encounter.start_date > #1/1/2020# AND dbo_Encounter.end_date > #1/1/2020#
ORDER BY dbo_Encounter.episode_number;
As you are still understanding the aggregate queries my suggestion is:
1-Create a query where you group by all fields and max(clpr_id). Save this as "Query1"
2-Create another query based on "Query1" and sort by "enco_id "

How to Distinct a sql query but still return all columns

This is my query:
SELECT dbo.Webs.Id, dbo.Webs.Title, dbo.Webs.FullUrl, dbo.Roles.RoleId,
dbo.Roles.Title AS RoleTitle, dbo.UserInfo.tp_Title, dbo.UserInfo.tp_Login
FROM dbo.RoleAssignment
INNER JOIN dbo.Roles ON dbo.RoleAssignment.SiteId = dbo.Roles.SiteId
AND dbo.RoleAssignment.RoleId = dbo.Roles.RoleId
INNER JOIN dbo.Webs ON dbo.Roles.SiteId = dbo.Webs.SiteId
AND dbo.Roles.WebId = dbo.Webs.Id
INNER JOIN dbo.UserInfo ON dbo.RoleAssignment.PrincipalId = dbo.UserInfo.tp_ID
WHERE tp_Title = 'HOBSON, Will';
This database contains all the permissions for the users of all sharepoint sites. I'm trying to create a query that displays all sites the user has access to. Currently it outputs a lot of duplicate information. I only want it to display results that have either a distinct Role Title or a distinct Web id.
So for example, in this query I would only want to see 4 results; 1, 5, 11 and 13.
(all this information is on a local test SharePoint installation that cannot be accessed externally, so the only information I'm giving away here is my name :))
Your query would be much easier to read with table aliases. The direct answer to your question is to use SELECT DISTINCT:
SELECT DISTINCT w.Id, w.Title, w.FullUrl, r.RoleId, r.Title AS RoleTitle,
ui.tp_Title, ui.tp_Login
FROM dbo.RoleAssignment ra INNER JOIN
dbo.Roles r
ON ra.SiteId = r.SiteId AND
ra.RoleId = r.RoleId INNER JOIN
dbo.Webs w
ON r.SiteId = w.SiteId AND
r.WebId = w.Id INNER JOIN
dbo.UserInfo ui
ON ra.PrincipalId = ui.tp_ID
WHERE tp_Title = 'HOBSON, Will';
However, it would be better to find the cause of the duplicates. Often duplicates like this are caused by incomplete join conditions. Fixing the join is the better approach, but sometimes SELECT DISTINCT is necessary.
You can just add a DISTINCT to your query:
SELECT DISTINCT dbo.Webs.Id, dbo.Webs.Title, dbo.Webs.FullUrl, dbo.Roles.RoleId,
dbo.Roles.Title AS RoleTitle, dbo.UserInfo.tp_Title, dbo.UserInfo.tp_Login
FROM dbo.RoleAssignment
INNER JOIN dbo.Roles ON dbo.RoleAssignment.SiteId = dbo.Roles.SiteId
AND dbo.RoleAssignment.RoleId = dbo.Roles.RoleId
INNER JOIN dbo.Webs ON dbo.Roles.SiteId = dbo.Webs.SiteId
AND dbo.Roles.WebId = dbo.Webs.Id
INNER JOIN dbo.UserInfo ON dbo.RoleAssignment.PrincipalId = dbo.UserInfo.tp_ID
WHERE tp_Title = 'HOBSON, Will';

SQL update statement inserting PeopleID into child tables to link data

I need to place the PeopleID in several tables for my new database to link all of the peole information. I have tried several times to write a simple update statement please help. Every time I get close I get AMBIGUOUS COLUMN ERROR I don't know what else to do.
Update CONTRACT
Set PeopleID = B.PeopleID
from People A
Inner join
(
Select PeopleId, F.ContractID
From People A
Inner Join Person PRSN on PRSN.PersonID = A.PersonID
Inner Join DARPA_IMPORT_REAL..persnl oldP on oldP.pl_pid = PRSN.PersonID
Left outer join Contract F on F.ContractID = oldP.kn_254id
) B on A.PeopleID = B.PeopleID
Go
try this
Update CONTRACT Set CONTRACT.PeopleID = B.PeopleID
from People A
Inner join (
Select A.PeopleId, F.ContractID
From People AA
Inner Join Person PRSN on PRSN.PersonID = AA.PersonID
Inner Join DARPA_IMPORT_REAL..persnl oldP on oldP.pl_pid = PRSN.PersonID
Left outer join Contract F on F.ContractID = oldP.kn_254id ) B
on A.PeopleID = B.PeopleID
you were asigning the ´A´ alias twice so I recomend using different aliases always

Left join not returning record with null

Here's the structure of my database (used to collect info from a survey):
question_responses->answer_choices->subquestions->questions->survey
| ^
V |
submissions->response_group<----------------------------survey_deployment
where A->B means A has the PK of B
So, I want to get the responses of a particular user; let's say that his submission pk is 1. I had written the query
select question_responses.answer_text
from submissions join question_responses on (question_responses.submission_pk = submission.pk)
join answer_choices on (question_responses.answer_choices_pk = answer_choices.pk)
join subquestions on (answer_choices.subquestions_pk = subquestions.pk)
right join questions on (subquestions.questions_pk = questions.pk)
where submissions.pk = 1
order by questions.order
It is possible to not answer questions. In such a case, there is no question_responses.pk recorded. I would still like to be able to account for skipping, so I need this record to be returned, even if there is no response. I thought that the right join would have accounted for this record, but apparently not.
Any help is greatly appreciated.
Because you have submissions.pk = 1 in the where clause this effectively turns your outer join into an inner join, since any missing submission will have a pk of null. and null = 1 is not true.
You could rewrite your query using a LEFT JOIN, and selecting from questions:
select question_responses.answer_text
from questions
left join (subquestions
inner join answer_choices
on answer_choices.subquestions_pk = subquestions.pk
inner join question_responses
on question_responses.answer_choices_pk = answer_choices.pk
inner join submissions
on question_responses.submission_pk = submission.pk)
on subquestions.questions_pk = questions.pk
and submissions.pk = 1
order by questions.order;
This is similar to doing something like:
select subquery.answer_text
from questions
left join
( select question_responses.answer_text, subquestions.questions_pk
from subquestions
inner join answer_choices
on answer_choices.subquestions_pk = subquestions.pk
inner join question_responses
on question_responses.answer_choices_pk = answer_choices.pk
inner join submissions
on question_responses.submission_pk = submission.pk
where submissions.pk = 1
) subquery
on subquery.questions_pk = questions.pk
order by questions.order;
but depending on your dbms the former may perform better as it has no derived tables.
Check out this, does it help?
SELECT question_responses.answer_text
FROM questions LEFT JOIN subquestions on (subquestions.questions_pk = questions.pk)
LEFT JOIN answer_choices on (answer_choices.subquestions_pk = subquestions.pk)
LEFT JOIN question_responses on (question_responses.answer_choices_pk = answer_choices.pk)
LEFT JOIN submissions on (question_responses.submission_pk = submission.pk)
WHERE submissions.pk = 1
ORDER BY questions.order

SQL query - How to show when data repeats itself for x number of entries

I am using SQL Server 2008 R2 Standard and I still very new to SQL Server.
I am trying to find when a x (measurement) has trend data that flatlines for longer than 48 intervals of the date time.
Thanks in advance.
My base query structure is
SELECT sites.site_name,
measurements.measurement_name,
trend_data_temp.trend_data_avg,
trend_data_temp.trend_data_time
FROM sites
INNER JOIN group_sites
ON sites.site_id = group_sites.site_id
INNER JOIN groups
ON group_sites.group_id = groups.group_id
INNER JOIN measurements
ON sites.site_id = measurements.site_id
INNER JOIN trend_data
ON measurements.measurement_id = trend_data.measurement_id
INNER JOIN trend_data_temp
ON measurements.measurement_id = trend_data_temp.measurement_id
GROUP BY sites.site_name,
measurements.measurement_name,
trend_data_temp.trend_data_avg,
trend_data_temp.trend_data_time
ORDER BY sites.site_name,
measurements.measurement_name
slightly in the dark without any outlines of input data and output data but maybe you need something like this (not tested)
SELECT
sites.site_name,
measurements.measurement_name,
trend_data_temp.trend_data_avg,
[occurances] = count(trend_data_temp.trend_data_time)
FROM sites
INNER JOIN group_sites
ON sites.site_id = group_sites.site_id
INNER JOIN groups
ON group_sites.group_id = groups.group_id
INNER JOIN measurements
ON sites.site_id = measurements.site_id
INNER JOIN trend_data
ON measurements.measurement_id = trend_data.measurement_id
INNER JOIN trend_data_temp
ON measurements.measurement_id = trend_data_temp.measurement_id
GROUP BY
sites.site_name,
measurements.measurement_name,
trend_data_temp.trend_data_avg
HAVING count(trend_data_temp.trend_data_time) >=48