SQL Query problem - sql

Consider two tables. Technician table has fields like T_ID,T_Name. Project table has fields like P_ID,P_Name, P_Date.
Now, since a Technician can work on many projects and a project can be done by many Technicians. Therefore, as evident, there is a many to many relationship between the two tables. Break the many to many, and create a new table called Assignment which consists of the foreign keys T_ID and P_ID.
Here is the question: I want to find out a list of who a particular technician (Technician with T_ID = 1 worked with over the last month (April/2011). For example if Technician 1 worked with Tech 2 and 3 then they qualify for the above query result and i would like tech 2 and Tech 3 T_ID T_name.
The answer can be also based on two queries linked.
Kindly let me know what will be the query for the mentioned problem.

This would find all the people who worked on assignments with the technician who has ID = 10. Maybe:
SELECT t.T_ID, t.T_Name
FROM Technician t, Project p, Assignments a
WHERE t.T_ID = a.T_ID and p.P_ID = a.P_ID
and a.P_ID IN (SELECT assign.P_ID FROM Assignments assign, Projects proj WHERE assign.T_ID = 10 and assign.P_ID = proj.P_ID and (proj.P_Date - getdate() <= 30))
The date is a little bit of a guess as I'm not sure on the syntax, however the rest should get the information you want.

Give Assignment table a primary key of its own (because composite keys suck).
The two ? characters represent the ID of the Technician that you're asking
who worked with. For example: "Who worked with Technician 5", the ? would be
5's.
SELECT
a1.T_ID
FROM
Assignment a1
WHERE
a1.A_ID IN (
SELECT assignment.A_ID
FROM Assignment a2
WHERE a2.T_ID = ?
)
AND a1.T_ID != ?
;

Related

How to select ALL results from a SQL query and eliminate the null values

Imagine I have four tables:
Agents
| agent_id | agent_name |
Teams
| team_id | team_name |agent_id |
Menu
| menu_id | menu_name |
Team_assignment
| menu_id | team_id|
I need to write a query that selects all agents that are assigned to all teams and all queues and disregard the ones that are not assigned to a queue. Note that every agent is always assigned to a team but it's not necessary that the agent is assigned to a queue.
Since you stated that this is for a school project, I'll try to stay within the guidelines mentioned here: How do I ask and answer homework questions?
From what I can make up from your question you basically want to select all the data from the different tables joining them on one of the columns in the first table a equals = a column from the second table b. Most commonly where the primary key from one table equals the foreign key from another table. Then you want to add conditions to your query where for example some column from table 1 equals = some value.
Do you catch my drift? 😏
No?
You want to SELECT a.*, b.* everything FROM table Agents a JOINing table Teams b ON column a.agent_id being equal to = column b.agent_id
You probably want to JOIN another table, lets say Team_assignment c ON column c.team_id being equal to = b.team_id.
You can JOIN more tables in the same way.
Sadly, I do not understand what you mean by the ones that are not assigned to a queue but it sounds like a condition that your query needs to match, so WHERE the potential column a.is_assigned_to_queue equals = true AND for example a.agent_name IS NOT NULL
If you got this far you should have been able to catch onto my drift 😎, congrats. This way hopefully you also got a better understanding of how building query works, instead of me just blatantly giving you the answer and you learn nothing from it. Like this:
SELECT a.*, b.*, c.*, d.* FROM Agents a
JOIN Teams b ON a.agent_id = b.agent_id
JOIN Team_assignment c ON c.team_id = b.team_id
JOIN Menu d ON d.menu_id = c.menu_id
WHERE a.is_assigned_to_queue = true
AND a.agent_name IS NOT NULL;
Now it is possible copy and pasting the snippet above will not work, that is because I'm not an SQL expert and I had to refresh my old memories about SQL myself by googling it. But that's the nice part of actually learning it. Being able to explain it to someone else :)

Looking to display records from Table A that have more than one relationship to Table B

This sounds like a very simple query but I have never needed this calculation before. I'm using SQL Management Studio and SQL Server 2008.
I have a table ct_workers which contains individual employees and a second table cs_facilities which shows the sites that they work at.
The table ct_workers has a field person which is the primary ID for each employee and has a field facility which links the employees to cs_facilities via a field guid
I'm looking to display all workers that have 2 or more facilities.
I've though about using Excel or rownumber but surely that must be a simple efficient way of doing this?
Can anyone assist please?
Thanks,
You can use a GROUP BY with HAVING
SELECT cw.person
FROM ct_workers cw
GROUP BY cw.person
HAVING COUNT(DISTINCT cw.facility) >= 2
Your question suggests that you can use aggregation:
select w.person
from ct_workers w
group by w.person
having min(w.facility) <> max(w.facility); -- at least 2 values
However, if the person is the unique key in ct_workers, then a person can only be in one facility. So, your question would not make sense. You should actually have a junction table with one row per person and per facility.

How to remove line duplicates SQL via compare two same table

How to remove duplicate values a = b and b = a?
with a as(select w.id , w.doc, w.org
, d.name_s, d.name_f, d.name_p, d.spec
, o.name, o.extid
from crm_s_workplaces w
join crm_s_docs d on d.id=w.doc
join crm_s_orgs o on o.id=w.org
where d.active=1 and d.cst='NY' and w.active=1 and w.cst='NY' and o.active=1
and
o.cst='NY')
select a1.doc, a2.doc,
a1.org,a1.name_s,a1.name_f,a1.name_p,a2.name_s,a2.name_f,a2.name_p from a a1
join a a2 on
a1.name_s=a2.name_s and
substr(a1.name_f,1,1)=substr(a2.name_f,1,1) and
substr(a1.name_p,1,1)=substr(a2.name_p,1,1) and
a1.org=a2.org and
a1.spec<>a2.spec
order by a1.name_s `enter code here`
ER model diagram:
Repeat example:
Sometimes comes across a1.spec > a2.spec:
What you are calling "duplicates" are actually not duplicates in your database.
You basically have multiple doc records for what could be the same person or not. See that even their names do not always match. For instace,
doc_id 1131385 has NAME_F = "Gabr" while
doc_id 1447530 has NAME_F = "Gabor"
In your database these are two different entities, and you cannot match them using primary key. You can try to join on the first, middle and last names, but as you can see in the above example with Gabor/Gabr, even that would not work.
Can you change the schema of the db? If so you need to separate the docs in one table - 1 record per doctor. And have the specialization in a separate table with the folloing columns:
spec_id (int, PK)
doc_id (foreign key to Doc table)
specialization
that way, if you have 1 doctor with 3 specs, he/she will show up only once in doc table, and multiple times in spec table.
I just notice something else. You have spec field in table workplaces. why? If you meant to say that Doc Gabor works as admin in hospital 1 but as a Therapist in hospital 2, you can do that. However, you have to remove the spec field from the doc table and only use the spec in workplaces table.

SQL JOIN returning multiple rows when I only want one row

I am having a slow brain day...
The tables I am joining:
Policy_Office:
PolicyNumber OfficeCode
1 A
2 B
3 C
4 D
5 A
Office_Info:
OfficeCode AgentCode OfficeName
A 123 Acme
A 456 Acme
A 789 Acme
B 111 Ace
B 222 Ace
B 333 Ace
... ... ....
I want to perform a search to return all policies that are affiliated with an office name. For example, if I search for "Acme", I should get two policies: 1 & 5.
My current query looks like this:
SELECT
*
FROM
Policy_Office P
INNER JOIN Office_Info O ON P.OfficeCode = O.OfficeCode
WHERE
O.OfficeName = 'Acme'
But this query returns multiple rows, which I know is because there are multiple matches from the second table.
How do I write the query to only return two rows?
SELECT DISTINCT a.PolicyNumber
FROM Policy_Office a
INNER JOIN Office_Info b
ON a.OfficeCode = b.OfficeCode
WHERE b.officeName = 'Acme'
SQLFiddle Demo
To further gain more knowledge about joins, kindly visit the link below:
Visual Representation of SQL Joins
Simple join returns the Cartesian multiplication of the two sets and you have 2 A in the first table and 3 A in the second table and you probably get 6 results. If you want only the policy number then you should do a distinct on it.
(using MS-Sqlserver)
I know this thread is 10 years old, but I don't like distinct (in my head it means that the engine gathers all possible data, computes every selected row in each record into a hash and adds it to a tree ordered by that hash; I may be wrong, but it seems inefficient).
Instead, I use CTE and the function row_number(). The solution may very well be a much slower approach, but it's pretty, easy to maintain and I like it:
Given is a person and a telephone table tied together with a foreign key (in the telephone table). This construct means that a person can have more numbers, but I only want the first, so that each person only appears one time in the result set (I ought to be able concatenate multiple telephone numbers into one string (pivot, I think), but that's another issue).
; -- don't forget this one!
with telephonenumbers
as
(
select [id]
, [person_id]
, [number]
, row_number() over (partition by [person_id] order by [activestart] desc) as rowno
from [dbo].[telephone]
where ([activeuntil] is null or [activeuntil] > getdate()
)
select p.[id]
,p.[name]
,t.[number]
from [dbo].[person] p
left join telephonenumbers t on t.person_id = p.id
and t.rowno = 1
This does the trick (in fact the last line does), and the syntax is readable and easy to expand. The example is simple but when creating large scripts that joins tables left and right (literally), it is difficult to avoid that the result contains unwanted duplets - and difficult to identify which tables creates them. CTE works great for me.

Design : multiple visits per patient

Above is my schema. What you can't see in tblPatientVisits is the foreign key from tblPatient, which is patientid.
tblPatient contains a distinct copies of each patient in the dataset as well as their gender. tblPatientVists contains their demographic information, where they lived at time of admission and which hospital they went to. I chose to put that information into a separate table because it changes throughout the data (a person can move from one visit to the next and go to a different hospital).
I don't get any strange numbers with my queries until I add tblPatientVisits. There are just under one millions claims in tblClaims, but when I add tblPatientVisits so I can check out where that person was from, it returns over million. I thinkthis is due to the fact that in tblPatientVisits the same patientID shows up more than once (due to the fact that they had different admission/dischargedates).
For the life of me I can't see where this is incorrect design, nor do I know how to rectify it beyond doing one query with count(tblPatientVisits.PatientID=1 and then union with count(tblPatientVisits.patientid)>1.
Any insight into this type of design, or how I might more elegantly find a way to get the claimType from tblClaims to give me the correct number of rows with I associate a claim ID with a patientID?
EDIT: The biggest problem I'm having is the fact that if I include the admissionDate,dischargeDate or the patientStatein the tblPatient table I can't use the patientID as a primary key.
It should be noted that tblClaims are NOT necessarily related to tblPatientVisits.admissionDate, tblPatientVisits.dischargeDate.
EDIT: sample queries to show that when tblPatientVisits is added, more rows are returned than claims
SELECT tblclaims.id, tblClaims.claimType
FROM tblClaims INNER JOIN
tblPatientClaims ON tblClaims.id = tblPatientClaims.id INNER JOIN
tblPatient ON tblPatientClaims.patientid = tblPatient.patientID INNER JOIN
tblPatientVisits ON tblPatient.patientID = tblPatientVisits.patientID
more than one million query rows returned
SELECT tblClaims.id, tblPatient.patientID
FROM tblClaims INNER JOIN
tblPatientClaims ON tblClaims.id = tblPatientClaims.id INNER JOIN
tblPatient ON tblPatientClaims.patientid = tblPatient.patientID
less than one million query rows returned
I think this is crying for a better design. I really think that a visit should be associated with a claim, and that a claim can only be associated with a single patient, so I think the design should be (and eliminating the needless tbl prefix, which is just clutter):
CREATE TABLE dbo.Patients
(
PatientID INT PRIMARY KEY
-- , ... other columns ...
);
CREATE TABLE dbo.Claims
(
ClaimID INT PRIMARY KEY,
PatientID INT NOT NULL FOREIGN KEY
REFERENCES dbo.Patients(PatientID)
-- , ... other columns ...
);
CREATE TABLE dbo.PatientVisits
(
PatientID INT NOT NULL FOREIGN KEY
REFERENCES dbo.Patients(PatientID),
ClaimID INT NULL FOREIGN KEY
REFERENCES dbo.Claims(ClaimID),
VisitDate DATE
, -- ... other columns ...
, PRIMARY KEY (PatientID, ClaimID, VisitDate) -- not convinced on this one
);
There is some redundant information here, but it's not clear from your model whether a patient can have a visit that is not associated with a specific claim, or even whether you know that a visit belongs to a specific claim (this seems like crucial information given the type of query you're after).
In any case, given your current model, one query you might try is:
SELECT c.id, c.claimType
FROM dbo.tblClaims AS c
INNER JOIN dbo.tblPatientClaims AS pc
ON c.id = pc.id
INNER JOIN dbo.tblPatient AS p
ON pc.patientid = p.patientID
-- where exists tells SQL server you don't care how many
-- visits took place, as long as there was at least one:
WHERE EXISTS (SELECT 1 FROM dbo.tblPatientVisits AS pv
WHERE pv.patientID = p.patientID);
This will still return one row for every patient / claim combination, but it should only return one row per patient / visit combination. Again, it really feels like the design isn't right here. You should also get in the habit of using table aliases - they make your query much easier to read, especially if you insist on the messy tbl prefix. You should also always use the dbo (or whatever schema you use) prefix when creating and referencing objects.
I'm not sure I understand the concept of a claim but I suspect you want to remove the link table between claims and patient and instead make the association between patient visit and a claim.
Would that work out better for you?