I have a table that shows the preference of a person to a school, like this
Person(name, preference_id)
/
School(school_id, name)
each person can have interest in multiple schools(shown by preference_id), like this:
Person(John, 132)
Person(John, 133)
School(132, UVA)
School(133, UMBC)
^John would like to go to either UVA or UMBC.
I want to write a query that displays ALL the school.name s for-each person.
select person.name, school.name
from Person, School
where person.preference_id = school.school_id
;
But what I have above would return in a 1 person- 1 school name ratio. Anyway I can modify this so it's 1 person - multi-schoolname? Thanks
SELECT p.name,
LISTAGG( s.name, ',' ) WITHIN GROUP ( ORDER BY s.name ) AS preferences
FROM Person p
INNER JOIN School s
ON ( p.preference_id = s.school_id )
GROUP BY p.name
Related
I am new to SQL and working on a list to generate employee list with their reporting VPs. the challenge that I have is that not all employees directly reports to VPs, some requires to go through multiple reporting channel to reach VPs.
What I did was creating CTE for each reporting channel and try to join but this method still does not work. For instance, if an employee A reports to supervisor, then supervisor reports to manager, then the manager reports to senior manager, then the senior manager reports to director, and the director reports to VP of their business unit, I need a table lists the information of employee A and the VP responsible for that business unit in following format
Employee number, firstname, lastname, username, jobtitle, VPusername
Below is the script I came up. Would someone please review and let me know what I am doing wrong?
Any help would be appreciated
With Employee
as
(
SELECT [EmployeeNumber]
,[SupervisorEmployeeNumber]
FROM [BASE_DB].[dbo].[HR_list_180604]
),
Tier1sup
as
(
SELECT sup1.[EmployeeNumber]
--,emp.[EmployeeNumber]
,sup1.[Username]
,sup1.[JobTitle]
,sup1.[SupervisorEmployeeNumber]
FROM [BASE_DB].[dbo].[HR_list_180604] sup1
left join Employee as emp on emp.[SupervisorEmployeeNumber] = sup1.[EmployeeNumber]
where sup1.[JobTitle] like '%VP,%'
),
Tier2sup
as
(
SELECT sup2.[EmployeeNumber]
--,emp.[EmployeeNumber]
,sup2.[Username]
,sup2.[JobTitle]
,sup2.[SupervisorEmployeeNumber]
FROM [BASE_DB].[dbo].[HR_list_180604] sup2
left join Tier1sup as tier1 on Tier1.[SupervisorEmployeeNumber] = sup2.[EmployeeNumber]
--left join Employee as emp on emp.[SupervisorEmployeeNumber] = Tier1sup.[SupervisorEmployeeNumber]
where sup2.[JobTitle] like '%VP,%'
),
Tier3sup
as
(
SELECT sup3.[EmployeeNumber]
--,emp.[EmployeeNumber]
,sup3.[Username]
,sup3.[JobTitle]
,sup3.[SupervisorEmployeeNumber]
FROM [BASE_DB].[dbo].[HR_list_180604] sup3
left join Tier2sup as tier2 on Tier2.[SupervisorEmployeeNumber] = sup3.[EmployeeNumber]
where sup3.[JobTitle] like '%VP,%'
)
select T1.[EmployeeNumber]
,T1.[FirstName]
,T1.[LastName]
,T1.[Username]
,T1.[JobTitle]
,case
when sup1.[JobTitle] like '%VP,%' then sup1.[Username]
when sup2.[JobTitle] like '%VP,%' then sup2.[Username]
when sup3.[JobTitle] like '%VP,%' then sup2.[Username]
end as SupUser
from [BASE_DB].[dbo].[HR_list_180604] T1
left join Employee as emp on T1.[EmployeeNumber] = emp.[EmployeeNumber]
left join Tier1sup as sup1 on sup1.[EmployeeNumber] = emp.[SupervisorEmployeeNumber]
left join Tier2sup as sup2 on sup2.[EmployeeNumber] = sup1.[SupervisorEmployeeNumber]
left join Tier3sup as sup3 on sup3.[EmployeeNumber] = sup2.[SupervisorEmployeeNumber]
I'm executing two queries. One that return the number of records and one that fetch the results. But the query where i only want the total of records , it takes the same time than the query that fetch the results. Why ? Here's my SQL. i'm using SQL 2014 :
(SELECT count(*) as id
FROM (
SELECT DISTINCT title, version
FROM book AS b
WHERE b.title IS NOT NULL AND NOT EXISTS (SELECT * FROM user AS u WHERE u.column1 = b.column1)
group by title, version
EXCEPT
SELECT DISTINCT title, version
FROM book AS b
WHERE b.title IS NOT NULL AND EXISTS (SELECT * FROM user AS u WHERE u.column2 = b.column1)
group by title, version
) c )
Try this:
(SELECT count(*) as id
FROM (
SELECT DISTINCT title, version
FROM book b left join user u on b.column1=u.column1
WHERE b.title IS NOT NULL and u.column1 is null
EXCEPT
SELECT DISTINCT title, version
FROM book b join user u on b.column1=u.column2
WHERE b.title IS NOT NULL
) c )
Hmmm . . . for performance, try removing the group by and select distinct (except does this anyway):
SELECT count(*) as id
FROM (SELECT title, version
FROM book b
WHERE b.title IS NOT NULL AND NOT EXISTS (SELECT 1 FROM user u WHERE u.column1 = b.column1)
EXCEPT
SELECT title, version
FROM book b
WHERE b.title IS NOT NULL AND EXISTS (SELECT 1 FROM user u WHERE u.column2 = b.column1)
) c;
Next: Be sure you have an index on user(column2) and user(column1).
With more information about the data, it might be possible to make further suggestions.
Hello Now I have 2 table .One of them is TEACHER, another INSTITUTE
I have a temp table #QUESTIONS. There are two row in this temp table
QuestionId,SenderType,SenderId
1,Teacher,475
2,Institute,1
Now if sender type is teacher i want to get teacher name and surname from TEACHER table,if sender type is institute i want to get institute name from INSTITUTE table
How can I do it ?
Thanks in advance
Lets try something different for this case. Look at the sample.
SELECT SENDERTYPE,Q.SENDERID,COALESCE(T.NAME,I.NAME) AS NAME,COALESCE(T.SURNAME,I.SURNAME) AS NAME FROM QUESTIONS Q
LEFT JOIN TEACHER T ON T.ID=Q.SENDERID AND Q.SENDERTYPE='TEACHER'
LEFT JOIN INSTITUTE I ON I.ID=Q.SENDERID AND Q.SENDERTYPE='INSTITUTE'
Use CASE Statement:
SELECT
Q.QuestionId,
Q.SenderType,
CASE Q.SenderType WHEN 'Teacher' THEN T.Name+ ' '+T.Surname ELSE I.Name END AS Name
FROM #tblQuestion Q
LEFT JOIN #tblTeacher T ON Q.SenderId=T.Id AND Q.SENDERTYPE='TEACHER'
LEFT JOIN #tblInstitute I ON Q.SenderId=I.Id AND Q.SENDERTYPE='INSTITUTE'
It can be achieved using UNION
SELECT q.SenderType ,
t.Name + ' ' + t.Surname Name
FROM #QUESTIONS q
JOIN TEACHER t ON q.SenderId = t.ID
WHERE q.SenderType = 'Teacher'
UNION ALL
SELECT q.SenderType ,
i.Name
FROM #QUESTIONS q
JOIN INSTITUTE i ON q.SenderId = i.ID
WHERE q.SenderType = 'Institute';
My SQL skills aren't great hence the post.
I'm trying to get all the contact names based on a company out.
For example I have two statements:
Select Id, CompanyName, Address From Clients
Select ClientId, ContactName From Contacts
You may have many contacts to a single client
Result: (I need all the contact names in a single column)
ContactName Company Address
----------------------------------------
Johh, Steve 123 Comp 12345 Address
David,Mike, Sarah 44 Comp 111 Address
A working example would be very much appreciated.
SELECT DISTINCT (
SELECT ISNULL(ct.ContactName, '') + ', '
FROM dbo.Clients cl JOIN dbo.Contacts ct ON cl.Id = ct.ClientId
WHERE cl.ID = cl2.Id
FOR XML PATH('')) AS ContactName, CAST(cl2.Id AS nvarchar(7)) + ' ' + cl2.CompanyName AS Company, Address
FROM dbo.Clients cl2
ORDER BY 2
Demo on SQLFiddle
Firstly build all the Contact Names for a Company into a Single Column. Assuming the database to be SQL Server, I'm using a Common Table Expression to store the single column contact list. Once the CTE is built, join it with the Clients table to get the ContactNames. FOR XML is used to concatenate rows.
WITH CTEContactList(ClientID,ContactNames)
AS
(
SELECT c1.ClientID,
Names = SUBSTRING(( SELECT ', ' + c2.ContactName
FROM Contacts c2
WHERE c1.ClientID = c2.ClientID
FOR XML PATH ('')),3,8000 ))
FROM Contacts c1
GROUP BY c1.ClientID
)
SELECT
cl.ID,
cl.CompanyName,
cl.Address,
ctelist.ContactNames
FROM Clients cl
INNER JOIN CTEContactList ctelist
ON cl.ID = cteList.ClientID
Sounds like you need to do a table join.
Example: two tables here
1. Person
2. Orders
Query:
SELECT
Persons.LastName, Persons.FirstName, Orders.OrderNo
FROM Persons
INNER JOIN Orders ON Persons.P_Id = Orders.P_Id
ORDER BY Persons.LastName
You didn't specify your DBMS, so I'm assuming PostgreSQL:
select string_agg(ct.contactName, ', '), cl.companyname, cl.address
from contacts ct
join clients cl on cl.id = ct.clientId
group by cl.companyname, cl.address
I want to select specific values from a table called Prescriptions. I want to select a patient that is utilizing the following medicines at a certain period in time:
This is the select that I have been using, but it returns patients that are utilizing just one or two of the medicines. I want to be able to bring just the patient that is utilizing both of the medicines:
SELECT MEDICINE, CLIENTNUMBER
FROM PRESCRIPTIONS
where
(MEDICINE like 'simvastatin %' OR
MEDICINE like 'amlodipine%')
AND
DATE between '11/23/2010' and '11/23/2010'
Group by CLIENTNUMBER, MEDICINE
Order by CLIENTNUMBER
Can anyone help? Thank you very much!
You could use two exists clauses to ensure the client has subscriptions for both medicines:
select p.MEDICINE
, p.CLIENTNUMBER
from PRESCRIPTIONS as p
where p.DATE between '11/23/2010' and '11/23/2011'
and exists
(
select *
from PRESCRIPTIONS as p2
where p2.DATE between '11/23/2010' and '11/23/2011'
and p2.CLIENTNUMBER = p.CLIENTNUMBER
and p2.MEDICINE like 'simvastatin %'
)
and exists
(
select *
from PRESCRIPTIONS as p3
where p3.DATE between '11/23/2010' and '11/23/2011'
and p3.CLIENTNUMBER = p.CLIENTNUMBER
and p3.MEDICINE like 'amlodipine %'
)
Try this:
SELECT p1.Medicine m1, p2.Medicine m2, p1.ClientNumber cn
FROM Prescriptions p1 INNER JOIN Prescriptions p2
ON p1.ClientNumber = p2.ClientNumber
WHERE (
((m1 LIKE 'simvastatin %') AND (m2 LIKE 'amlodipine%')) OR
((m2 LIKE 'simvastatin %') AND (m1 LIKE 'amlodipine%'))
AND Date BETWEEN '11/23/2010' AND '11/23/2010')
GROUP BY cn, m1
ORDER BY cn
you must create a table for your medician an then get division of prescription on it.