Access query to remove a group of records - sql

I'm trying to create a query in MS Access that only provides records where, when grouped if one of the criteria is TRUE, then that group is not included in the resultant data set.
I have the following fields ID, Teacher_Name, Dsp_Prd, Course_Key, Long_Description, Sec, Tot_Stds, Contains_CC, SchoolCode, IsCoTeach.
A teacher can appear multiple times in a given period (DSP_prd). However if they are assigned to a class as an assistant (IsCoTeach=TRUE) then all of the classes that they appear in should be filtered from the dataset.
For example:
The results should be:
Thanks for your help!

You can use not exists:
select t.*
from SchoolData as t
where not exists (
select 1
from SchoolData as t1
where t1.teacher_name = t.teacher_name and t1.dsp_prd = t.dsp_prd and t1.IsCoTeach = 'TRUE'
)

Related

Can we select data from 2 tables in same time

From the code as shown below. I wonder that why it can select data from 2 tables in same time that are table "venue AS v" and table "as s".
or I misunderstand?
SELECT name, s.num_match
FROM venue AS v,
(SELECT venue_id, COUNT(*) AS num_match
FROM match
GROUP BY venue_id) AS s
WHERE v.venue_id = s.venue_id
LIMIT 3;
Yes you can using JOIN clause for example.
More infos here: https://www.informit.com/articles/article.aspx?p=30875&seqNum=5
Yes you can select data from as many as tables you want at the same time.
In this case you are trying to get an aggregated number from table-s and join it with the table v.
There are many ways to write the code to join the table. Above is one method which you have used.

Count Distinct in MS Access - How to count number of accounts with at least one activity of a certain type?

I have a list of activities where one field is AccountName indicating the name of the person. There is another field called ActivityType.
Basically I want to return the number of accounts that have at least one ActivityType that is equal to RET (indicating a returned item). Since a person may have multiple returns in a given year I don't want to count the number of returns total, just the number of accounts that have at least one RET.
I've tried various combinations of select statements, count statements, having statements, it's just not working right.
Here is what I tried:
Select DISTINCT Count(Activities.AccountName) AS CountOfAccountName
FROM Activities
GROUP BY Activities.ActivityType
HAVING (Activities.ActivityType = "RET")
But this seems to return a much larger number than if I just do the select statement:
SELECT DISTINCT Activities.AccountName
FROM Activities
WHERE (Activities.ActivityType = "RET")
I think you need a simple COUNT and GROUP BY function. Since Access doesn't allow Count Distinct, You need to first select distinct records and then count them -
SELECT Count(T.AccountName) AS CountOfAccountName
FROM (SELECT AccountName
FROM Activities
WHERE Activities.ActivityType = 'RET'
GROUP BY AccountName) T;
This will filter only those records having ActivityType = 'RET' and then will count the distinct AccountName.
Use a subquery:
SELECT Count(*) AS ActiveAccounts
FROM
(SELECT DISTINCT AccountName
FROM Activities
WHERE ActivityType = "RET")
If activity/types cannot be duplicated, then you can simply use:
select count(*) AS CountOfAccountName
from Activities
where Activities.ActivityType = "RET";
If they can be, then you need a subquery as shown in other answers.

SELECT list expression references column user_id which is neither grouped nor aggregated at [8:5]

I have 2 data sets. One of all patients who got ill (endo-2) and one of a special group of patients that also exists in endo-2 called "xp-56"
I've been trying to run this query and I'm not sure why it isn't working. I want to do counts of 3 columns in endo-2 of those patients that belong in the xp-56 table.
this is the code I've been using with the following error
SELECT list expression references column user_id which is neither grouped nor aggregated at [8:5]
how do I fix this so I never make the same mistake again!
SELECT
Virus_Exposure,
Medical_Delivery,
Number_of_Site
FROM
(
SELECT
medical_id,
COUNT(DISTINCT Virus_id) AS Virus_Exposure,
COUNT(EndoCrin_id) AS Medical_Delivery,
COUNT (site_id_clinic) AS Number_of_Site
FROM
`endo-2`
WHERE
_PARTITIONTIME BETWEEN TIMESTAMP("2017-12-15")
AND TIMESTAMP("2018-01-10")) AS a
RIGHT JOIN
(
SELECT
medical_id
FROM
`xp-56`
ORDER BY
medical_id DESC) AS b
ON
a.medical_id=b.medical_id
GROUP BY
medical_id
Why doesnt the medical_id in table a work?
Why not just do this?
SELECT e.medical_id,
COUNT(DISTINCT e.Virus_id) AS Virus_Exposure,
COUNT(e.EndoCrin_id) AS Medical_Delivery,
COUNT(e.site_id_clinic) AS Number_of_Site
FROM `endo-2` e JOIN
`xp-56` x
ON x.medical_id = e.medical_id
WHERE e._PARTITIONTIME BETWEEN TIMESTAMP("2017-12-15") AND TIMESTAMP("2018-01-10")
GROUP BY e.medical_id;

SQL Server : join on array of ID's from previous join

I have 2 tables. One has been pruned to show only ID's which meet certain criteria. The second needs to be pruned to show only data that matches the previous "array" of id's. there can be multiple results.
Consider the following:
Query_1_final: Returns the ID's of users whom meet certain criteria:
select
t1.[user_id]
from
[SQLDB].[db].[meeting_parties] as t1
inner join
(select distinct
[user_id]
from
[SQLDB].[db].[meeting_parties]
group by
[user_id]
having
count([user_id]) = 1) as t2 on t1.user_id = t2.user_id
where
[type] = 'organiser'
This works great and returns:
user_id
--------------------
22
1255
9821
and so on...
It produces a single column with the ID's of everyone who is a "Meeting Organizer" and also in the active_meetings table. (note, there are multiple types/roles, this was the best way to grab them all)
Now, I need this data to filter another table, another join. Here is the start of my query
Query_2_PREP: returns 5 columns where the meeting has "started" already.
SELECT
[meeting_id]
,[meeting_style]
,[meeting_day]
,[address]
,[promos]
FROM
[SQLDB].[db].[all_meetings]
WHERE
[meeting_started] = 'TRUE'
This works as well
meeting_id | meeting_style | meeting_day ...
---------------------------------------------
23 open M,F,SA
23 discussion TU,TH
23 lead W,F
and so on...
and returns ALL 10,982 meetings that started, but I need it to return only the meetings that are from the distinct 'organiser's ID's from Query_1_final (which should be more like 1200 records or so)
Ideally, I need something "like" this below (but of course it does not work)
Query 2: needs to return all meetings that are from organiser ID's only.
SELECT
[meeting_party_id]
,[meeting_style]
,[meeting_day]
,[address]
,[promos]
FROM
[SQLDB].[db].[all_meetings]
WHERE
[meeting_started] = 'TRUE'
AND [meeting_party_id] = "ANY Query_1_final results, especially multiple"
I have tried nesting JOIN and INNER JOIN's but I think there is something fundamental I am missing here about SQL. In PHP I would use an array compare or just run another query... any help would be much appreciated.
Just use IN. Here is the structure of the logic:
with q1 as (
<first query here>
)
SELECT m.*
FROM [SQLDB].[db].[all_meetings] m
WHERE meeting_started = 'TRUE' AND
meeting_party_id IN (SELECT user_id FROM q1);

How to eliminate duplicate rows based on column max value in sql?

I have a view which returns duplicate rows having field performance, which can be 1,2,3 or 4. I need to select only rows which is having max performance. How to do this ? Tried this :
View :
results needed as follows :
So basically for each employee number group, I need to fetch what is max calender value and corresponding performance value
You can express
the employee record with the highest performance
as:
there is no record (for this employee) with a higher performance
And that gives:
SELECT * FROM employee e
WHERE NOT EXISTS (
SELECT *
FROM employee nx
WHERE nx.employee_nr = e.employee_number
AND nx.performance > e.performance
);
You need to do two queries: read max calender for any given employee group, then to select the rows with the same those values is calender and group.
Select vm."Employee Number" as eGroup, max(vm.Calender) as Calender From view1 vm
That part is obvious. The problem is how to inject it as a criterion for
Select vd."Employee Number", vd.Calender, vd.Performance From view1 vd where ... ?
Since aggregate functions (like max) gives a singular result, you can use JOIN without risk of having Cartesian sets production (when all combinations of rows from two selects are tried, NxM)
Select vd."Employee Number", vd.Calender, vd.Performance From view1 vd
Join (Select "Employee Number" as eGroup, max(vm.Calender) as maxCal From view1) as vm
On (vd."Employee Number" = vm.eGroup) and (vd.Calender = vm.maxCal)
Note, this still can produce several rows with the same Employee Number and Calender if that was how they were in the table. Unless you have a UNIQUE INDEX upon both those columns.
Thanks all for your inputs. I tried a slightly different approach for this.
Step 1 : Since I did not have any unique identifier for each row, I made one by concatenating Employee_Number and Calender columns.
It becomes easier then and we can use following :
SELECT DISTINCT
T1.EMPLOYEE_NUMBER, T1.Performance, T1.Calender
FROM dbo.view1 AS T1 LEFT OUTER JOIN dbo.view1 AS T2
ON T2.EMPLOYEE_NUMBER = T1.EMPLOYEE_NUMBER
AND T2.maxval > T1.maxval
WHERE (T2.maxval IS NULL)
Here Maxval is Concatenated column.
Actual answer is here : SQL Server: Only last entry in GROUP BY
Your stated goal doesn't match your results, but I would do this (at least in DB2):
select e.Employee_Number, e.Calendar, e.Performance
from Employee e
where e.Calendar in (select max(Calendar) from Employee group by Employee_Number)
select v1.performance,max(v1.field)
from view1 v1
group by v1.performance