Creating Report, repetition in report output, Ms Access SQL - sql

SELECT NMC.*, Exam.Final_Exam_Level
FROM
(SELECT Technicians.Technician_ID AS Technician_ID,
Technicians.First_Name AS First_Name,
Technicians.Surname AS Surname,
MAX(New_Models.Date_Issued) AS Last_Course_Date,
MAX(New_Models.Issue) AS Last_Issue,
MAX(New_Models.Model_ID) AS Last_Model_ID,
Technicians.Course_Level AS No_Training_Courses
FROM New_Models, New_Models_Allocation, Technicians
WHERE New_Models.Model_ID=New_models_Allocation.Model_ID
And Technicians.Technician_ID=New_Models_Allocation.Technician_ID
GROUP BY Technicians.Technician_ID, Technicians.Course_Level, First_Name, Surname
ORDER BY MAX(New_Models.Model_ID) DESC)
AS NMC
INNER JOIN (SELECT Technicians.Technician_ID, COUNT(*) AS Final_Exam_Level
FROM Technicians, Exams, Exam_Allocation
WHERE (Technicians.Technician_ID)=Exam_Allocation.Technician_ID
And ((Exams.Exam_ID)=Exam_Allocation.Exam_ID)
And (Exams.Date_Taken)<=#12/31/2010#
GROUP BY Technicians.Technician_ID, Technicians.Course_Level
ORDER BY Technicians.Technician_ID)
AS Exam ON Exam.Technician_ID=NMC.Technician_ID;
This query shows each technician, Last Exam, Last New_Model, Last course.
SELECT Technicians.Technician_ID, Jobs.Job_ID, Jobs.Date_Occured, Fix
FROM Technicians, Jobs, Tech_Allocation, Recovery
WHERE Technicians.Technician_ID=Tech_Allocation.Technician_ID
And Jobs.Job_ID=Tech_Allocation.Job_ID
And Jobs.Job_ID=Recovery.Job_ID
And Jobs.Date_Occured>=#1/1/2010#
And Jobs.Date_Occured<=#12/31/2010#
ORDER BY Fix;
This query shows the jobs each technician has done.
However, when creating a report in Ms Access, the jobs are repeated. Hence, instead of a technician having done 3 jobs, it shows 12 for example. Although when running the second query itself, results aren't repeated.
Any Help?

For obvious reasons, I don't usually read other people's SQL queries, but your example was very well formatted. Is this the problem?
INNER JOIN (SELECT Technicians.Technician_ID, COUNT(*) AS Final_Exam_Level
...
GROUP BY Technicians.Technician_ID, Technicians.Course_Level
These 2 lines are from the 2nd subquery of your first query. You have 1 index field (Technician_ID), but 2 grouping fields (Technician_ID and Course_Level). This would produce results like:
Technician_ID Final_Exam_Level
Bob 5
Bob 4
Nadine 5
I recommend either removing Course_Level from the Group By or adding it to the Select row.

Related

Having SQL Server choose and show one record over other

Ok, hopefully I can explain this accurately. I work in SQL Server, and I am trying to get one row from a table that will show multiple rows for the same person for various reasons.
There is a column called college_attend which will show either New or Cont for each student.
My issue: my initial query narrows down the rows I'm pulling by Academic Year, which consists of two semesters: Fall of one year, and Spring of the following to create an academic year. This is why there are two rows returned for some students.
Basically, I need to generate an accurate count of those that are "New" and those that are "Cont", but I don't want both records for the same student counted. They will have two records because they will have one for spring and one for fall (usually). So if a student is "New" in fall, they will have a "Cont" record for spring. I want the query to show ONLY the "New" record if they have both a "New' and "Cont" record, and count it (which I will do in Report Builder). The other students will basically have two records that are "Cont": one for fall, and one "Cont" for spring, and so those would be considered the continuing ones or "Cont".
Here is the basic query I have so far:
SELECT DISTINCT
people.people_id,
people.last_name,
people.first_name,
academic.college_attend AS NewORCont,
academic.academic_year,
academic.academic_term,
FROM
academic
INNER JOIN
people ON people.people_id = academic.people_id
INNER JOIN
academiccalendar acc ON acc.academic_year = academic.academic_year
AND acc.academic_term = academic.academic_term
AND acc.true_academic_year = #Academic_year
I'm not sure if this can be done with a CASE statement? I thought of a GROUP BY, but then SQL Server will want me to add all of my columns to the GROUP BY clause, and that ends up negating the purpose of the grouping in the first place.
Just a sample of what I work with for each student:
People ID
Last
First
NeworCont
12345
Soanso
Guy
New
12345
Soanso
Guy
Cont
32345
Person
Nancy
Cont
32345
Person
Nancy
Cont
55555
Smith
John
New
55555
Smith
John
Cont
---------
------
-------
----------
Hopefully this sheds some light on the duplicate record issue I mentioned.
Without sample data its awkward to visualize the problem, and without the expected results specified it's also unclear what you want as the outcome. Perhaps this will assist, it will limit the results to only those who have both 'New' and 'Cont' in a single "true academic year" but the count seems redundant as this (I imagine) will always be 2 (being 1 New term and 1 Cont term)
SELECT
people.people_id
, people.last_name
, people.first_name
, acc.true_academic_year
, count(*) AS count_of
FROM academic
INNER JOIN people ON people.people_id = academic.people_id
INNER JOIN academiccalendar acc ON acc.academic_year = academic.academic_year
AND acc.academic_term = academic.academic_term
AND acc.true_academic_year = #Academic_year
GROUP BY
people.people_id
, people.last_name
, people.first_name
, acc.true_academic_year
HAVING MAX(academic.college_attend) = 'New'
AND MIN(academic.college_attend) = 'Cont'

sql join and minus

I seem to be having problem getting a certain query to work. I know I'm so close. Here's a copy of my er diagram
I think I am so close to achieving what I want to do with this code, only I get invalid identifier when trying to run it. I think its because the practice is being changed somehow after joining, as I am only getting invalid identifier on row 5?
SELECT staffid, staff_firstname, staff_surname, practice.practice_name, practice.practice_city
from staff
join practice on staff.practiceid = practice.practiceid
MINUS
SELECT staffid, staff_firstname, staff_surname, practice.practice_name, practice.practice_city
from staff
where role = 'GP';
Basically I'm trying to use the minus construct to find practices which do not employ a GP and include some information such as the CITY and practice_address.
I can use the minus construct to find out how many staff do not have the role of GP like so:
SELECT staffid, staff_firstname, staff_surname
from staff
MINUS
SELECT staffid, staff_firstname, staff_surname
from staff
where role = 'GP';
where I get the results:
STAFFID STAFF_FIRS STAFF_SURN
__________ __________ __________
8 NYSSA THORNTON
9 MONA BRADSHAW
10 GLORIA PENA
I'm struggling to use the join with the minus construct to get information about the GP's practice address and city etc.
Any help would be greatly appreciated!
The second select, after the minus, is referring to columns from the practice table - but it doesn't join to it:
SELECT staffid, staff_firstname, staff_surname,
practice.practice_name, practice.practice_city
from staff
join practice on staff.practiceid = practice.practiceid
MINUS
SELECT staffid, staff_firstname, staff_surname,
practice.practice_name, practice.practice_city
from staff
join practice on staff.practiceid = practice.practiceid
where role = 'GP';
That isn't going to give you what you want though, it will just remove the rows for staff that are GPs, not all trace of practices that have any GPs - non-GP staff at all practices will still be shown.
if you don't want the remaining staff details you only need to include the columns from the practice table in the select lists, and the minus would then give you what you want (and Gordon Linoff has shown two alternatives to minus in that case). If you do want the remaining staff details then you can use a not-exists clause rather than a minus - something like:
select s.staffid, s.staff_firstname, s.staff_surname,
p.practice_name, p.practice_city
from staff s
join practice p on s.practiceid = p.practiceid
where not exists (
select 1
from staff s2
where s2.practice_id = p.practice_id
and s2.role = 'GP
);
This is similar to Gordon's second query but has an extra join to staff for the details. Again, if you don't want those, use Gordon's simpler query.
You could also use an aggregate check, or could probably do something with an analytic function if you've learned abput those, to save having to hit the tables twice.
Your original query only operates on the level of "staff", not "practice". I would be inclined to solve this using aggregation:
select p.practice_name, p.practice_city
from staff s join
practice p
on s.practiceid = p.practiceid
group by p.practice_name, p.practice_city
having sum(case when s.role = 'GP' then 1 else 0 end) = 0;
Or, even better:
select p.*
from practice p
where not exists (select 1
from staff s
where s.practiceid = p.practiceid and s.role = 'GP'
);
I think this is the simplest and most direct interpretation of your question.

How to sum employee paychecks from multiple jobs into one table

table featuring fictitious employee data, area ( in hectares (ha)) cleared (noted in french as superficie), rate for 1 hectare of cleared land on the specific lot (french:taux) and amount due( expr1) for that lot.
My problem here is that I want the total amount due for each Worker, not the amount due for each worker for each lot. Totals for Sirs Alain, Jacques, Paul, Roger and Tanguay should normally be 4066, 4082 , 5638, 5811 and 3131 , respectively.
My code so far is this
SELECT tbl_Employés.Num_deb, tbl_Employés.Prénom, tbl_Employés.Nom, tbl_Employés.Age, tbl_Employés.DEP, tbl_Employés.Expérience, tbl_Employés.Adresse, Tbl_terrain.superficie, Tbl_terrain.Taux, [superficie]*[taux] AS [Montant à payer]
FROM tbl_Employés INNER JOIN Tbl_terrain ON tbl_Employés.Num_deb = Tbl_terrain.Num_deb
ORDER BY tbl_Employés.Nom;
I have so far tried to use GROUP BY Numéro_terrain, which returns an error that my query does not include the specified expression ''Num_deb'' as a part of an aggregation fuction
I woul greatly appreciate any imput. I am very sorry if you have a hard time understanding some words, as I am doing my best to translate everything from french.
One method is to include all the columns in the GROUP BY that are not arguments to aggregation functions:
SELECT e.Num_deb, e.Prénom, e.Nom, e.Age, e.DEP, e.Expérience, e.Adresse,
SUM([superficie]*[taux]) AS [Montant à payer]
FROM tbl_Employés as e INNER JOIN
Tbl_terrain as t
ON e.Num_deb = t.Num_deb
GROUP BY e.Num_deb, e.Prénom, e.Nom, e.Age, e.DEP, e.Expérience, e.Adresse
ORDER BY e.Nom;

SQL Query Removing Dups

Using GoldMine CRM and wrote this query to try and find out people in our system based on a record Type, Lead Creation Date and Last Contact Date. Now when running the query it brings up multiple results say for John Smith it is showing me all of his information rather than just the last contacted date which I want. I'll paste the query below any help would be much appreciated.
SELECT DISTINCT CONTACT1.CONTACT AS Contact_Name,
Min(CONTACT1.CONTACT),
CONTACT1.KEY1 AS Rec_Type,
CONTACT1.CREATEON AS Lead_Type,
CONTHIST.LASTDATE AS Last_Contact,
CONTHIST.RESULTCODE AS Stamp
FROM CONTACT1
INNER JOIN CONTHIST
ON CONTACT1.ACCOUNTNO = CONTHIST.ACCOUNTNO
WHERE CONTACT1.KEY1 = 'Lead'
GROUP BY CONTACT1.CONTACT,
CONTACT1.KEY1,
CONTACT1.CREATEON,
CONTHIST.LASTDATE,
CONTHIST.RESULTCODE
HAVING Count(CONTACT1.CONTACT) = 1
ORDER BY CONTACT1.CREATEON

How to combine to values from two records

Hi guys so I have the following code that should look at a event cost, figure out from a transaction table if its been fully paid and from that display the unpaid balance.
Select CASESTUDY_CLIENT.CLEINT_FNAME as First_Name,
casestudy_client.client_sname as Surname,
casestudy_client.client_Phonenumber as Phone_number,
casestudy_event.event_totalcost- casestudy_transaction.transaction_value as Unpaid_balance
from casestudy_client
inner join casestudy_event
on casestudy_client.client_id = casestudy_event.event_clientid
inner join casestudy_transaction
on casestudy_event.event_id = casestudy_transaction.transaction_eventid
where casestudy_event.EVENT_EVENTSTAGE ='complete' and
casestudy_event.event_totalcost > casestudy_transaction.transaction_value;
This works perfectly however if we have a multi part transaction then it fails to pick up the matching event id and assumes its another event.
In my test data I have an event that costs £500, one transaction that has a value of 400 and one transaction with a value of 99. The current output shows the two records one with an unpaid balance of 100 and the other with 401. What I would like to show is just 99
If this is possible in relatively simple way please let me know as I can't figure out how to make it work
You need to add together transactions.
Select CASESTUDY_CLIENT.CLEINT_FNAME as First_Name,
casestudy_client.client_sname as Surname,
casestudy_client.client_Phonenumber as Phone_number,
casestudy_event.event_totalcost- sum(casestudy_transaction.transaction_value) as Unpaid_balance
from casestudy_client
inner join casestudy_event
on casestudy_client.client_id = casestudy_event.event_clientid
inner join casestudy_transaction
on casestudy_event.event_id = casestudy_transaction.transaction_eventid
where casestudy_event.EVENT_EVENTSTAGE ='complete' and
casestudy_event.event_totalcost > casestudy_transaction.transaction_value
GROUP BY CASESTUDY_CLIENT.CLEINT_FNAME, casestudy_client.client_sname, casestudy_client.client_Phonenumber, casestudy_event.event_totalcost
Also, CLEINT_FNAME is probably a typo.
It appears you want to sum the transaction values before subtracting them from the cost.
Select CASESTUDY_CLIENT.CLEINT_FNAME as First_Name,
casestudy_client.client_sname as Surname,
casestudy_client.client_Phonenumber as Phone_number,
casestudy_event.event_totalcost- casestudy_transaction.transaction_value as Unpaid_balance
from casestudy_client
inner join casestudy_event
on casestudy_client.client_id = casestudy_event.event_clientid
inner join (
select casestudy_transaction.transaction_eventid, sum(transaction_value) as transaction_value
from casestudy_transaction
group by casestudy_transaction.transaction_eventid
) as casestudy_transaction
on casestudy_event.event_id = casestudy_transaction.transaction_eventid
where casestudy_event.EVENT_EVENTSTAGE ='complete'
and casestudy_event.event_totalcost> casestudy_transaction.transaction_value ;
I would probably left join the transactions subquery though so you can include the events that haven't been paid for yet, but that just depends on the goal of the query.