Inputting data into a table from two different tables - sql

I have these 3 tables with data
SQL> select * from subject;
SUBJECTID LNAME FNAME PROJID
---------- ------------ ---------- ----------
10011 Indy Eva XYZ01
20022 Jordan Sam XYZ01
30033 Jordan Mary XYZ01
40044 Belmont Renee XYZ02
50055 Pissaro Becky XYZ02
60066 Nadal Becky XYZ03
70077 Bardot Brigitte XYZ03
80088 null Eva XYZ03
90099 Garnet Larry XYZ04
10111 Isner Monica XYZ04
11011 Dupont Marty XYZ05
11 rows selected.
SQL> select * from project;
PROJID MEDICNAME PURPOSE START_DATE END_DATE PI_ID
---------- ---------- ------------ ----------- ----------- ----------
XYZ02 Medic1 diabetes 01-oct-2018 31-jul-2022 10001
XYZ01 Medic1 foot 01-sep-2019 31-jul-2021 10001
XYZ04 Medic3 spleen 10-jan-2019 31-jul-2021 10001
XYZ05 Medic5 spleen 10-jul-2020 1-jan-2021 10002
XYZ03 Medic3 lung 01-nov-2016 31-dec-2022 10002
SQL> select * from researcher;
PID LNAME FNAME
---------- ------------ ----------
10001 Elgar Dawn
10002 Jordan Daniel
10003 Jordan Athena
10004 Rivers Karen
10005 Gomez Tracy
10006 Gomez Jenny
10007 Perry Eva
10008 McHale Vicky
8 rows selected.
and then created a third table that looks like this
SQL> CREATE TABLE n_subject
2 (SubjID number(7),
3 Lastname varchar2(12),
4 Firstname varchar2(10));
I want to populate my new table with the Subjects who were involved in projects that were lead by Dawn Elgar (PID is 10001). Is there a way to do that across 3 tables? I am close with code that looks like this
SQL> insert into n_subject (subjid, lastname, firstname)
2 select subjectid, lname, fname
3 from subject where projid = 'XYZ01' or projid = 'XYZ02' or projid = 'XYZ04';
but am trying to get the data in there across all the three tables instead, using the ProjectId and the PID. Is this possible?

you can use select with inner join statement
INSERT INTO n_subject
(subjid, lastname, firstname)
SELECT subjectid,
lname,
fname
FROM [subject]
JOIN [project]
ON [project].projid = [subject].projid
WHERE [project].pi_id = '10001';

Related

Pivot Rows into column value

I have data like below:
Employer_ID Gender First_Name Last_Name Keywords
----------- ------ ---------- ---------- ---------
101 M Ian SMITH Environment
101 M Ian SMITH Global warmimg
101 M Ian SMITH Earth
101 M Ian SMITH Air
101 M Ian SMITH Sound pollution
102 M Scott Tiger Heart attack
102 M Scott Tiger Medical
102 M Scott Tiger Heart surgery
I would like to have output as below. Group by Employer_Id, Gender, First_Name and Last_Name. All relevant Keywords should be merged to produce one row per Employer_Id, Gender, First_Name and Last_Name:-
Employer_ID Gender First_Name Last_Name Keywords
----------- ------ ---------- --------- ---------
101 M Ian SMITH Environment Global warmimg Earth Air Sound pollution
102 M Scott Tiger Heart attack Medical Heart surgery
You can achieve it using String AGG as suggested by #Zhorov,
SELECT Employer_ID,Gender,First_Name,Last_Name,STRING_AGG(Keywords ,' ') AS Keywords
FROM #Temp
GROUP BY Employer_ID,Gender,First_Name,Last_Name

Using CASE WHEN To Update

I have a few tables that look like
select * from stipend
order by subjectid, stipdate;
SUBJECTID STIPDATE AMOUNT
---------- ----------- ----------
10011 31-oct-2021 800
10111 31-jul-2019 2000
10111 31-jul-2021 1500
20022 31-jul-2020 1200
30033 29-feb-2020 1400
40044. 31-jul-2020 1200
40044 31-jul-2021 2000
50055 31-jul-2021 2000
50055 30-sep-2021 1000
select * from subject
order by subjectid;
SUBJECTID LNAME FNAME PROJID
---------- ------------ --------------------
10011 Indy Eva XYZ01
10111 Isner Monica XYZ04
11011 Dupont Marty XYZ05
20022 Jordan Sam XYZ01
30033 Jordan Mary XYZ01
40044 Belmont Renee XYZ02
50055 Pissaro Becky XYZ02
60066 Nadal Becky XYZ03
70077 Bardot Brigitte XYZ03
80088 null Eva XYZ03
90099 Garnet Larry XYZ04
And I want to update the stipends that are in Project XYZ01 and XYZ02 by 40% using the CASE WHEN construct. Obviously the two tables are connect by stipend.subjectid = subject.subjectid and the I would use the subject.projectid to determine this, but how would I do that with CASE WHEN?
This is how I did it before
update stipend
set amount = amount + (amount * .40)
where subjectid in
(select subjectid from subject
where subject.projid = 'XYZ01' or subject.projid = 'XYZ02');
and that worked, but now I need to do the same thing but with CASE WHEN.
Eddie, below is a solution that uses the CASE WHEN statement. But, as Mureinik mentioned on the comments, your solution is better than using a CASE WHEN statement in this case.
-- using CASE WHEN
update s
set s.amount = (case when x.projid in ('XYZ01','XYZ02')
then s.amount + (s.amount * .40)
else s.amount
end)
from stipend s
join subject x on x.subjectid = s.subjectid
Note: I did not add x.projid in ('XYZ01','XYZ02') to the where clause as that would defeat the purpose of using the CASE WHEN. So, this would run for all the rows.

Find duplicate batches based on multiple columns

I have a table that contains a series of related records (batches). Each batch has a unique id and can contain customer payments. I want to find if a batch is duplicate even if it is submitted on different days.
A batch can have 1 or more records. Here is sample data set:
BatchId InputAmount CustomerName BatchDate
------- ----------- ------------ ----------
182944 $475.00 Barry Smith 16-Mar-2019
182944 $260.00 John Smith 16-Mar-2019
182944 $265.00 Jane Smith 16-Mar-2019
182944 $400.00 Sara Smith 16-Mar-2019
182944 $175.00 Andy Smith 16-Mar-2019
182945 $475.00 Barry Smith 16-Mar-2019
182945 $260.00 John Smith 16-Mar-2019
182945 $265.00 Jane Smith 16-Mar-2019
182945 $400.00 Sara Smith 16-Mar-2019
182945 $175.00 Andy Smith 16-Mar-2019
183194 $100.00 Paul Green 21-Mar-2019
183195 $100.00 Nancy Green 21-Mar-2019
183197 $150.00 John Brown 20-Mar-2019
183197 $210.00 Sarah Brown 20-Mar-2019
183198 $150.00 John Brown 21-Mar-2019
183198 $210.00 Sarah Brown 21-Mar-2019
183200 $125.00 John Doe 20-Mar-2019
183200 $110.00 Sarah Doe 20-Mar-2019
183202 $125.00 John Doe 21-Mar-2019
183202 $110.00 Sarah Doe 21-Mar-2019
183202 $115.00 Paul Rudd 21-Mar-2019
Batches (182944, 182945) and (183197,183198) are duplicate while the other batches are not.
I thought maybe I could create a summary table with counts and sums and get close but I'm having trouble finding the true duplicates by including the names as well.
DECLARE #Summaries TABLE(
BatchId INT,
BatchDate DATETIME,
BatchCount INT,
BatchAmount MONEY)
-- Summarize the Data so we can look for duplicates
INSERT INTO #Summaries
SELECT a.BatchId, a.BatchDate, COUNT(*) AS RecordCount, SUM(a.InputAmount) AS BatchAmount
FROM Batches a
WHERE a.BatchDate BETWEEN '20190316' and '20190321'
GROUP BY a.BatchId, a.BatchDate
ORDER BY a.BatchId DESC
-- find the potential duplicate batches based on the Counts and Sums
SELECT A.* FROM #Summaries A
INNER JOIN (SELECT BatchCount, BatchAmount, BatchDate FROM #Summaries
GROUP BY BatchCount, BatchAmount, BatchDate
HAVING COUNT(*) > 1) B
ON A.BatchCount = B.BatchCount
AND A.BatchAmount = B.BatchAmount
WHERE DATEDIFF(DAY, a.BatchDate, b.BatchDate) BETWEEN -1 AND 1
Thank you for the help. I'm using a SQL Server 2012 database.
you can try like below
with cte as
(select BatchId from table_name
group by BatchId
having count(*)>1
) select * from table_name a where a.BatchId in (select BatchId from cte)

How do I transpose multiple rows to columns in SQL

My first time reading a question on here.
I am working at a university and I have a table of student IDs and their supervisors, some of the students have one supervisor and some have two or three depending on their subject.
The table looks like this
ID Supervisor
1 John Doe
2 Peter Jones
2 Sarah Jones
3 Peter Jones
3 Sarah Jones
4 Stephen Davies
4 Peter Jones
4 Sarah Jones
5 John Doe
I want to create a view that turns that into this:
ID Supervisor 1 Supervisor 2 Supervisor 3
1 John Doe
2 Peter Jones Sarah Jones
3 Peter Jones Sarah Jones
4 Stephen Davies Peter Jones Sarah Jones
5 John Doe
I have looked at PIVOT functions, but don't think it matches my needs.
Any help is greatly appreciated.
PIVOT was the right clue, it only needs a little 'extra' :)
DECLARE #tt TABLE (ID INT,Supervisor VARCHAR(128));
INSERT INTO #tt(ID,Supervisor)
VALUES
(1,'John Doe'),
(2,'Peter Jones'),
(2,'Sarah Jones'),
(3,'Peter Jones'),
(3,'Sarah Jones'),
(4,'Stephen Davies'),
(4,'Peter Jones'),
(4,'Sarah Jones'),
(5,'John Doe');
SELECT
*
FROM
(
SELECT
ID,
'Supervisor ' + CAST(ROW_NUMBER() OVER(PARTITION BY ID ORDER BY Supervisor) AS VARCHAR(128)) AS supervisor_id,
Supervisor
FROM
#tt
) AS tt
PIVOT(
MAX(Supervisor) FOR
supervisor_id IN ([Supervisor 1],[Supervisor 2],[Supervisor 3])
) AS piv;
Result:
ID Supervisor 1 Supervisor 2 Supervisor 3
1 John Doe NULL NULL
2 Peter Jones Sarah Jones NULL
3 Peter Jones Sarah Jones NULL
4 Peter Jones Sarah Jones Stephen Davies
5 John Doe NULL NULL
You will notice that the assignment to Supervisor X is done by ordering by the Supervisor-VARCHAR. If you want the ordering done differently, you might want to include an [Ordering] column; then change to ROW_NUMBER() OVER(PARTITION BY ID ORDER BY [Ordering]). Eg an [Ordering] column could be an INT IDENTITY(1,1). I'll leave that as an excercise to you if that's what's really needed.

How does select query works?

I having trouble with this query
it is executing quit well but I cannot make out
how is this select statement working.
Any help or explanation on this problem will be appreciated ..
thank you
these are my tables and query
here am looking for the employee who lives in same city as the the company for which they work
Table:-emp
eid name street city
----------- ---------------- ------------- ------------
1 yeman asd vasai
2 aksh adssd mumbai
3 chintan ghfgh mumbai
4 samual ghfdgh bandra
5 ddlj fghfgh andheri
6 jack fghnfg Bandra
7 bridge gfhfgh vasai
8 rahim ghfgh mumbai
9 chirag fghfghfg bandra
10 mistry hhhty bandra
11 ravi tytey andheri
Table:- company
cid companyname city
----------- ------------------- ------------
1 Vasai Industries vasai
2 Mumbai Pharmacy mumbai
3 bandra loft bandra
4 andheri tactics andheri
Table:= works
eid cid salary
----------- ----------- -----------
1 1 200
2 3 4831
3 4 4457
4 2 20001
5 1 32221
6 2 224
7 3 784
8 1 336
9 3 2489
10 2 4789
11 1 22541
Query
select * from emp
where eid
IN (select eid from works
where cid=(select cid from company
where city=emp.city))
why not use this query with joins and its easy to understand then a bunch of subqueries.
select * from emp
inner join works on works.eid = emp.eid
inner join company on company.city=emp.city
Explanation:
1.select cid from company where city=emp.city
Here you are getting city id regarding cities which are same in emp and company
2.
select eid from works
where cid=(select cid from company
where city=emp.city)
Here you getting collection of id's from works table which cid is same in emp and company
3.
select * from emp
where eid
IN (select eid from works
where cid=(select cid from company
where city=emp.city))
here you are getting all records based on emp id's whose cities are same in emp and city