I have the following tables:
PATIENT PRACTICE
- PATIENT_ID - PRACTICE_ID
- PATIENT_NAME - PRACTICE_NAME
- PRACTICE_ID
These tables keep track of patients who attend medical practices. I need to use a COUNT operation to count the number of patients that each practice has, then order the results by ascending order of number of patients.
The following is the desired output:
PracticeName NumberOfPatients
North Medical 3
East Medical 4
South Medical 5
West Medical 6
I have tried this so far, but it doesn't count it as I expected:
SELECT BRANCH.BRANCH_NAME, COUNT(EMPLOYEE.EMP_NUM)
FROM EMPLOYEE, BRANCH
GROUP BY BRANCH.BRANCH_NAME, EMPLOYEE.EMP_NUM;
This is a pretty trivial question and you should have done some rudimentary research before asking it, which is why someone voted your question down.
For the sake of helping the new guy out, here is a query that will give you those results.
SELECT pr.Practice_Name, COUNT(pa.Patent_ID) as NumberOfPatients
FROM practice pr INNER JOIN patient pa ON pr.practice_id = pa.practice_id
GROUP BY pr.practice_name
ORDER BY COUNT(pa.patientid)
You seem to be rather new to SQL, so your question is a little bit fuzzy. Try this:
select pra.practice_name,
count(pat.patient_id) as NumberOfPatients
from patient as pat inner join practice as pra on (pat.practice_id = pra.practice_id)
group by pra.practice_name
And learn the basics of joining tables to get a better understanding of SQL.
Related
I'm new to SQL and am a bit confused on how I would write a query in order to get the count of state in a different table.
Ie i have this table [student]
id
school_code
0
0123
1
2345
2
2345
And this other table [school]
school_code
name
State
0123
xxyy
New Jersey
2345
xyxy
Washington
3456
yxyx
Colarado
I want to find out how I would get this table which tells me the entries for state by checking each student and making a count of how often that state occurs, ordered by most occurrences in student table.
State
No. times occured (iterating through student)
Washington
2
New Jersey
1
SELECT school.state, count(school.state)
FROM student, school
WHERE student.school_code = school.school_code
GROUP BY school.state
ORDER BY count(school.state)`
I'm not sure whether this would be iterating through each student and counting them?
Or just natural-joinging student and school and then counting all the states
When I run this on data supplied, the numbers of times occurred is a really low number which doesn't seem right?
We can simply JOIN the two tables and COUNT the school code in the students table, with GROUP BY state:
SELECT
sc.state, COUNT(st.school_code)
FROM
school sc
JOIN student st
ON sc.school_code = st.school_code
GROUP BY sc.state;
We can try out here: db<>fiddle
I'm trying to find the match no in which Germany played against Poland. This is from https://www.w3resource.com/sql-exercises/soccer-database-exercise/sql-subqueries-exercise-soccer-database-4.php. There are two tables : match_details and soccer_country. I don't understand how the count(distinct) works in this case. Can someone please clarify? Thanks!
SELECT match_no
FROM match_details
WHERE team_id = (
SELECT country_id
FROM soccer_country
WHERE country_name = 'Germany')
OR team_id = (
SELECT country_id
FROM soccer_country
WHERE country_name = 'Poland')
GROUP BY match_no
HAVING COUNT(DISTINCT team_id) = 2;
As Lamak mentioned, what an ugly consideration for a query, but many ways to approach a query.
As mentioned, counting for (Distinct team_id) makes sure that there are only 2 unique teams. If there is ever a Cartesian result, you could get repetition of multiple rows showing more than one instance of both teams. So the count of distinct on the TEAM_ID eliminates that.
Now, that said, Other "team" query data structures I have seen have a single record for the match and a column for EACH TEAM playing the match. That is easier by a long-shot, but still a relatively easy query.
Break the query down a little, and consider a large scale set of data (not that this, or any sort of even professional league would have such large record counts to give delay with a sql engine).
Your first criteria is games with Germany. So lets start with that.
SELECT
md1.match_no
FROM
match_details md1
JOIN soccer_country sc1
on md1.team_id = sc1.country_id
AND sc1.country_name = 'Germany'
So, why even look at any other record/match if Germany is not even part of the match on either side. Of which this in itself would return 6 matches from the sample data of 51 matches. So now, all you need to do is join AGAIN to the match details table a second time for only those matches, but ALSO the second team is Poland
SELECT
md1.match_no
FROM
match_details md1
JOIN soccer_country sc1
on md1.team_id = sc1.country_id
AND sc1.country_name = 'Germany'
-- joining again for the same match Germany was already qualified
JOIN match_details md2
on md1.match_no = md2.match_no
-- but we want the OTHER team record since Germany was first team
and md1.team_id != md2.team_id
-- and on to the second country table based on the SECOND team ID
JOIN soccer_country sc2
on md2.team_id = sc2.country_id
-- and the second team was Poland
AND sc2.country_name = 'Poland'
Yes, may be a longer query, but by eliminating 45 other matches (again, thinking a LARGE database), you have already saved blowing through tons of data to a very finite set. And now finishing only those Germany / Poland. No aggregates, counts, distincts, just direct joins.
FEEDBACK
Lets take a look at some BAD sample data... which as all programmers know, there is no such thing (NOT). Anyhow, lets take a look at these few matches.
Match Team ID blah
52 Poland Just put the names here for simplistic purposes
52 Poland
53 Germany
53 Germany
If you were to run the query without DISTINCT Teams, both match 52 and 53 would show up... As Poland is one team and appears 2 times for match 52, and similarly Germany 2 times for match 53. By doing DISTINCT Team, you can see that for each match, there is only 1 team being returned and thus excluded. Does that help? Again, no such thing as bad data :)
And yet another sample match where more than 2 teams created
Match Team ID
54 France
54 Poland
54 England
55 Hungary
56 Austria
In each of these matches, NONE would be returned. Match 54 has 3 distinct teams, and Match 55 and 56 only have single entry, thus no opponent to compete against.
2nd FEEDBACK
To clarify the query. If you look at the short query for just Germany, that aliased instance of "md1" is already sitting on any given record for a Germany match. So the second join to the "md2", I only care about the same match, so I can join on the same match_no. However, in the "md2" alias, the "!=" means NOT EQUAL. ! = logical NOT. So the join is saying from the MD1, join to the MD2 alias on the same match id. However, only give me where the teams are NOT the same. So the first instance holds Germany's team ID (already qualified) and thus give me the secondary team id. So now I can use the secondary (md2) instance team ID to join to the country to confirm only for Poland.
Does this now clarify things for you?
I have some horse data in a table and am practicing SQL while following my hobby. I would like to find an elegant way to solve this problem. Right now I have this convoluted way of getting the answer but I know there HAS to be an easier way.
Description:
I'll make it really simple (Assume these 8 rows are the entire table). I have a table with 4 columns. HORSE_ID, NAME, TRACK, Date
A horse might run at one track or many different tracks. The end goal is to find what only the horses who have ran/campaigned at only one specific track....in this case, I want to see the horses that have run all their races at SA (Santa Anita)
HORSE_ID NAME TRACK DATE
1 JUSTIFY SA FEB-2018
2 JUSTIFY PIM MAY-2018
3 JUSTIFY BEL JUN-2018
4 KANTHAKA SA DEC-2017
5 KANTHAKA SA JAN-2018
7 THREE RULES GP JUL-2016
8 DABSTER SA JAN-2018
So if I ran this query with this data, the only horses I would expect to see are KANTHAKA, and DABSTER because they are the only horses that only ran all their races at Santa Anita track. So say next month KANTHAKA ran at ANOTHER DIFFERENT track, then the next time the query was run, only DABSTER would show up.
Does this make sense?
Try using GROUP BY with HAVING:
SELECT NAME
FROM yourTable
GROUP BY NAME
HAVING MIN(TRACK) = MAX(TRACK);
Writing the HAVING clause as above is preferable to writing HAVING COUNT(DISTINCT TRACK) = 1. The reason for this is that the above query can make use of an index on (NAME, TRACK).
If in addition you wish to restrict to a single track, then we can try:
SELECT NAME
FROM yourTable
GROUP BY NAME
HAVING MIN(TRACK) = MAX(TRACK) AND MIN(TRACK) = 'SA';
You can do a subquery requesting the count of distinct tracks to be 1 using GROUP BY and HAVING COUNT DISTINCT and then select those WHERE the track is 'SA':
SELECT NAME
FROM
(SELECT NAME, MIN(TRACK) as TRACK
FROM HORSES
GROUP BY 1
HAVING COUNT (DISTINCT TRACK) = 1) horses_one_race
WHERE
TRACK = 'SA'
I hit this issue regularly but here is an example....
I have a Order and Delivery Tables. Each order can have one to many Deliveries.
I need to report totals based on the Order Table but also show deliveries line by line.
I can write the SQL and associated Access Report for this with ease ....
SELECT xxx
FROM
Order
LEFT OUTER JOIN
Delivery on Delivery.OrderNO = Order.OrderNo
until I get to the summing element. I obviously only want to sum each Order once, not the 1-many times there are deliveries for that order.
e.g. The SQL might return the following based on 2 Orders (ignore the banalness of the report, this is very much simplified)
Region OrderNo Value Delivery Date
North 1 £100 12-04-2012
North 1 £100 14-04-2012
North 2 £73 01-05-2012
North 2 £73 03-05-2012
North 2 £73 07-05-2012
South 3 £50 23-04-2012
I would want to report:
Total Sales North - £173
Delivery 12-04-2012
Delivery 14-04-2012
Delivery 01-05-2012
Delivery 03-05-2012
Delivery 07-05-2012
Total Sales South - £50
Delivery 23-04-2012
The bit I'm referring to is the calculation of the £173 and £50 which the first of which obviously shouldn't be £419!
In the past I've used things like MAX (for a given Order) but that seems like a fudge.
Surely there must be a regular answer to this seemingly common problem but I can't find one.
I don't necessarily need the code - just a helpful point in the right direction.
Many thanks,
Chris.
A roll up operator may not look pretty. However, it would do the regular aggregates that you see now, and it show the subtotals of the order. This is what you're looking for.
SELECT xxx
FROM
Order
LEFT OUTER JOIN
Delivery on Delivery.OrderNO = Order.OrderNo
GROUP BY xxx
WITH ROLLUP;
I'm not exactly sure how the rest of your query is set up, but it would look something like this:
Region OrderNo Value Delivery Date
North 1 £100 12-04-2012
North 1 £100 14-04-2012
North 2 £73 01-05-2012
North 2 £73 03-05-2012
North 2 £73 07-05-2012
NULL NULL f419 NULL
I believe what you want is called a windowing function for your aggregate operation. It looks like the following:
SELECT xxx, SUM(Value) OVER (PARTITION BY Order.Region) as OrderTotal
FROM
Order
LEFT OUTER JOIN
Delivery on Delivery.OrderNO = Order.OrderNo
Here's the MSDN article. The PARTITION BY tells the SUM to be done separately for each distinct Order.Region.
Edit: I just noticed that I missed what you said about orders being counted multiple times. One thing you could do is SUM() the values before joining, as a CTE (guessing at your schema a bit):
WITH RegionOrders AS (
SELECT Region, OrderNo, SUM(Value) OVER (PARTITION BY Region) AS RegionTotal
FROM Order
)
SELECT Region, OrderNo, Value, DeliveryDate, RegionTotal
FROM RegionOrders RO
INNER JOIN Delivery D on D.OrderNo = RO.OrderNo
Struggling getting a query to work……..
I have two tables:-
tbl.candidates:
candidate_id
agency_business_unit_id
tbl.candidate_employment_tracker
candidate_id
The candidate employment can have duplicate records of a candidate_id as it contains records on their working history for different clients.
The candidates tables is unique for each candidate.
I'm trying to obtain results which will group by agency_business_unit_id and count the amount of candidates each has which exist in the candidate_employment_tracker.
E.g.
Agency Business Unit Id | Candidates
------------------------------------------------------------
100 | 2
987 | 1
12 | 90
The query I'm working on doesn't appear to be working as I'm getting the count of the candidates in candidate_employment_tracker.
SELECT
abu.agency_business_unit_id,
abu.agency_business_unit_name,
count(c.candidate_id) AS candidateCount
FROM candidate_employment_tracker cet
INNER JOIN candidate c ON c.candidate_id = cet.candidate_id
INNER JOIN agency_business_unit abu ON abu.agency_business_unit_id = c.agency_business_unit_id
WHERE c.candidate_ni_number NOT REGEXP '^[A-CEGHJ-PR-TW-Z][A-CEGHJ-NPR-TW-Z] ?[0-9]{2} ?[0-9]{2} ?[0-9]{2} ?[ABCD]$'
GROUP BY abu.agency_business_unit_id
ORDER BY abu.agency_business_unit_name ASC
I've tried several approaches and the results are inconsistent. For instance I know one of the agency business units only has 1 candidate but the result is 2. This is as a result of this particular candidate having 2 records in the candidate employment tracker table. I'll keep bashing away but any help would be much appreciated.
Do you need
count(DISTINCT c.candidate_id)
That would avoid the double counting where candidates have 2 records in the candidate employment tracker table.
Hmmm this doesn't appear to work now that I look further into the results. When I compare the candidates for a agency business unit I get inconsistent count numbers.