MS Access Count unique values of one table appearing in second table which is related to a third table - sql

I am working with my lab database and close to complete it. But i am stuck in a query and a few similar queries which all give back the similar results.
Here is the Query in design mode
and this is what it gives out
This query is counting the number of ID values in table PatientTestIDs whereas I want to count the number of unique PatientID values grouped by each department
I have even tried Unique Values and Unique Records properties but all the times it gives the same result.

What you want requires two queries.
Query1:
SELECT DISTINCT PatientID, DepartmentID FROM PatientTestIDs;
Query2:
SELECT Count(*) AS PatientsPerDept, DepartmentID FROM Query1 GROUP BY DepartmentID;
Nested all in one:
SELECT Count(*) AS PatientsPerDept, DepartmentID FROM (SELECT DISTINCT PatientID, DepartmentID FROM PatientTestIDs) AS Query1 GROUP BY DepartmentID;
You can include the Departments table in query 2 (or the nested version) to pull in descriptive fields but will have to include those additional fields in the GROUP BY.

Related

Why sometimes a subquery can work like using 'group by'

I'm new to sql and can't understand why sometimes a subquery can work like using 'group by'.
Say, there are two tables in a data base.
'food' is a table crated by:
CREATE TABLE foods (
id integer PRIMARY KEY,
type_id integer,
name text
);
'foods_episodes' is a table created by:
CREATE TABLE foods_episodes (
food_id integer,
episode_id integer
);
Now I'm using the following two sqls and generating the same result.
SELECT name, (SELECT count(*) FROM foods_episodes WHERE food_id=f.id) AS frequency
FROM foods AS f
ORDER BY name;
SELECT name, count(*) AS frequency
FROM foods_episodes,
foods AS f
WHERE food_id=f.id
GROUP BY name;
So why the subquery in the first sql works like it group the result by name?
When I run the subquery alone:
SELECT count(*)
FROM foods_episodes,
foods f
WHERE food_id=f.id
the result is just one row. Why using this sql as a subquery can generate multi-rows result?
The first query isn't actually grouping by name. If you have more than 1 record with the same name (different ID), you will see it being displayed twice (hence, not grouped by).
The first query uses what is called a correlated subquery, it calculates the subquery (the inner SELECT) once for each row of the outmost select. Because the FROM in this outmost SELECT is just from the table foods, you will get one record for each food + the results of the subquery, thus no need to group.

MS Access Query / Design

I have a table with instances of employee events. Each row has an ID, employee name and an eventNumber among other data. I would like to find and count all instances of where “employee name” occurs in this table, thus counting all the events associated with that employee.
If there are 15 unique employees , I suppose I could write 15 separate queries to get this done. But, is there a more efficient way to do this?
Also, I would like to display the total number of events for each employee that gets returned from these queries in another table or visual display of some sorts. This is where I really don’t know what to do as I haven’t used access much but am much more familiar with SQL.
Thanks for everyone who could take some time to chime in with some advice. I appreciate it a lot
This is fairly straight-forward in SQL. You can GROUP BY the employee name to get an overall count. Adding GROUP BY to a SQL statement will allow you to perform aggregate functions on one or more columns. Aggregate functions include COUNT, SUM, MIN, and MAX.
Documentation about GROUP BY can be found here:
https://support.office.com/en-us/article/group-by-clause-84eeb766-25d2-4aa1-8eea-002bb65ef3a0
A couple examples:
This query groups by EmployeeName to get the total count of all rows in table by employee name.
SELECT
EmployeeName
, COUNT(*) AS NumberOfEvents
FROM table
GROUP BY EmployeeName
Additionally, if you would like to get counts by eventid and employee name, you can group by both employee name and eventid. The query will then show the count of each type of event for each employee name.
SELECT
EmployeeName
, EventId
, COUNT(*) AS NumberOfEvents
FROM table
GROUP BY
EmployeeName
, EventId
If you would like to filter the results so that only one employee, 'Leroy Jenkins' is shown then you can add a WHERE clause as well, like this:
SELECT
EmployeeName
, COUNT(*) AS NumberOfEvents
FROM table
WHERE EmployeeName = "Leroy Jenkins"
GROUP BY EmployeeName
Responding to #WesG's comment asking for clarification.
The aggregate functions, like COUNT, are "rolling up" several rows in a table and displaying a single value for those rows. If your SELECT statement does not contain a GROUP BY clause, then the aggregate functions are working on all rows in the table.
When you do have a GROUP BY clause, then the aggregate functions will work on each group of rows that all have the same values in the columns by which you are grouping. Also, if you include a GROUP BY clause, then you may not SELECT columns that you are not GROUPing BY.
So, if you have a table like this:
CREATE TABLE [dbo].[AuditTrailLogs](
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[EventType] nvarchar(20) NOT NULL,
[EventId] [int] NOT NULL,
[Message] [nvarchar](max) NULL,
[WhoDidIt] [nvarchar](50) NULL,
[WhenOccurredUtc] [datetime] NOT NULL,
[EntityPayload] [nvarchar](max) NULL,
)
You could count the total number of rows in the table like this:
SELECT COUNT(*) AS NumLogEntries
FROM dbo.AuditTrailLogs
If you wanted to count rows by the user who made the entry:
SELECT WhoDidIt, COUNT(*) AS NumLogEntries
FROM dbo.AuditTrailLogs
GROUP BY WhoDidIt
Then Access is going to split the rows in the table into a number of groups and COUNT will return the number log entries for each distinct value of WhoDidIt in the table.
If you want to see the totals by user who made the log entry and event type, then you could group by both columns:
SELECT WhoDidIt, EventType, COUNT(*) AS NumLogEntries
FROM dbo.AuditTrailLogs
GROUP BY WhoDidIt, EventType
Now, the NumLogEntries in each row of the result set will be the total of each event type that each user made.
Access will complain if you try to do something like this, though:
SELECT Id, WhoDidIt, EventType, COUNT(*) AS NumLogEntries
FROM dbo.AuditTrailLogs
GROUP BY WhoDidIt, EventType
If you think about it, this query doesn't make sense. The COUNT aggregate functions says you want to roll up multiple rows and display a single value for all those rows, however, you're also asking to see a value that isn't part of a group and is different for each row in the table.
something like
select employeeName, count(*) as nbEvents
from myTable
group by employeeName

How can BigQuery SQL give different DISTINCT and GROUP BY results?

We seem to be getting two different, mutually incompatible results from legacy SQL and standard SQL in Google Big Query.
Here is our standard SQL Query...which gives an answer with 218,529 rows.
SELECT DISTINCT(EID)
FROM test.ourBQtable
Here is our legacy SQL Query...
SELECT COUNT(EID) AS Total, EID
FROM [ourBQproject:test.ourBQtable]
GROUP BY EID
ORDER BY Total DESC
This shows results that look like the table below but yet also shows 218,529 rows of results:
Total EID
376 jb+qLvHMm5JrMkNybAi6uC75FzgsGcNQhJ19IeWFDcQ=
352 JGqNBgicm+mpcYBS4K7AI2WXI3xaSgMkktb+7oOjjnQ=
How is it possible to have what appears to be duplicate EIDs (376 of them as shown in one case in the table) - but when using the DISTINCT(EID) command - the number of rows doesn't decrease? Shouldn't DISTINCT be filtering out all the duplicate rows? Do we really have duplicate rows?
What are we missing in our understanding?
Your code appears to be working exactly correctly.
DISTINCT EID is saying that there are 218,529 different values of EID. This should be returning one row for each of the 218,529 different EIDs.
When you use GROUP BY, you are getting one row for each of the EIDs. In this case, you get the same number.
Try running this query:
SELECT COUNT(*) as num_rows, COUNT(DISTINCT EID) as num_eids
FROM test.ourBQtable;
This will show the number of rows in the table and the number of distinct values of EID (ignoring NULL values)`.
Below two query are equivalent and return same number or rows - one per each unique EID
SELECT DISTINCT EID
FROM test.ourBQtable
and
SELECT EID
FROM test.ourBQtable
GROUP BY EID
That explains why number of output rows are the same
Now, in second query you added COUNT(EID)
SELECT COUNT(EID) AS Total, EID
FROM test.ourBQtable
GROUP BY EID
this does not change the number of output rows, but rather adds count of rows in test.ourBQtable with respective EID (if you sum all these counts - you will get total rows in the original table)

SQL: Find duplicates and for each duplicate group assign value of first duplicate of that group

I have the results in the top table. I would like the results in the bottom table.
Using an SQL query on the table above, I would like to find groups of duplicates (where the values in all columns except Id and Category are identical) and from that create a result that has for each entry the lowest Id from its group of duplicates and the (unmodified) Category from the original table.
Window function min can be used here:
select min(id) over (partition by first_name, last_name, company) id,
category
from t;

How to insert a count column into a sql query

I need the second column of the table retrieved from a query to have a count of the number of rows, so row one would have a 1, row 2 would have a 2 and so on. I am not very proficient with sql so I am sorry if this is a simple task.
A basic example of what I am doing would be is:
SELECT [Name], [I_NEED_ROW_COUNT_HERE],[Age],[Gender]
FROM [customer]
The row count must be the second column and will act as an ID for each row. It must be the second row as the text file it is generating will be sent to the state and they require a specific format.
Thanks for any help.
With your edit, I see that you want a row ID (normally called row number rather than "count") which is best gathered from a unique ID in the database (person_id or some other unique field). If that isn't possible, you can make one for this report with ROW_NUMBER() OVER (ORDER BY EMPLOYEE_ID DESC) AS ID, in your select statement.
select Name, ROW_NUMBER() OVER (ORDER BY Name DESC) AS ID,
Age, Gender
from customer
This function adds a field to the output called ID (see my tips at the bottom to describe aliases). Since this isn't in the database, it needs a method to determine how it will increment. After the over keyword it orders by Name in descending order.
Information on Counting follows (won't be unique by row):
If each customer has multiple entries but the selected fields are the same for that user and you are counting that user's records (summed in one result record for the user) then you would write:
select Name, count(*), Age, Gender
from customer
group by name, age, gender
This will count (see MSDN) all the user's records as grouped by the name, age and gender (if they match, it's a single record).
However, if you are counting all records so that your whole report has the grand total on every line, then you want:
select Name, (select count(*) from customer) as "count", Age, Gender
from customer
TIP: If you're using something like SSMS to write a query, dragging in columns will put brackets around the columns. This is only necessary if you have spaces in column names, but a DBA will tend to avoid that like the plague. Also, if you need a column header to be something specific, you can use the as keyword like in my first example.
W3Schools has a good tutorial on count()
The COUNT(column_name) function returns
the number of values (NULL values will not be counted) of the
specified column:
SELECT COUNT(column_name) FROM table_name;
The COUNT(*) function returns the number of records in a table:
SELECT COUNT(*) FROM table_name;
The COUNT(DISTINCT column_name) function returns the number of
distinct values of the specified column:
SELECT COUNT(DISTINCT column_name) FROM table_name;
COUNT(DISTINCT) works with ORACLE and Microsoft SQL Server, but
not with Microsoft Access.
It's odd to repeat the same number in every row but it sounds like this is what you're asking for. And note that this might not work in your flavor of SQL. MS Access?
SELECT [Name], (select count(*) from [customer]), [Age], [Gender]
FROM [customer]