Joining table twice with output based n new table - sql

I am having trouble joining a table twice on the same column.
Table People
name
phone_number
Pamela
113 555 7544
Jordan
328 555 9658
Haley
502 555 6712
Table Phone_calls
caller
receiver
duration
113 555 7544
328 555 9658
234
328 555 9658
502 555 6712
500
502 555 6712
113 555 7544
468
Desired output
duration
caller_name
receiver_name
234
Pamela
Jordan
SELECT name as caller_name, name as receiver_name, duration
FROM people
JOIN phone_calls ON people.phone_number=phone_calls.caller
JOIN phone_calls ON people.phone_number=phone_calls.receiver
ORDER BY duration;
How should differentiate the two name links I want to output?

This is where aliases make for an easier query:
select pc.duration, c.Name as Caller_name, r.Name as Receiver_name
from Phone_calls pc
join People c on c.phone_number = pc.caller
join People r on r.phone_number = pc.receiver
order by pc.duration;

I'm not sure if I understood your question correctly but, assuming the desired output you've mentioned is indeed the output you desire, this query correctly returns your output:
create table people (
nome varchar(50) primary key,
phone_number varchar(50)
);
insert into people values ('Pamela', '113 555 7544');
insert into people values ('Jordan', '328 555 9658');
insert into people values ('Haley', '502 555 6712');
select * from people;
create table phone_calls (
caller varchar(50),
receiver varchar(50),
durations int
);
insert into phone_calls values ('113 555 7544', '328 555 9658', 234);
insert into phone_calls values ('328 555 9658', '502 555 6712', 500);
insert into phone_calls values ('502 555 6712', '113 555 7544', 468);
select
tt.durations,
tt.caller_name,
p.nome as "receiver_name"
from
(
select
pc.durations,
p.nome as caller_name,
pc.receiver as telefone
from people p
left join phone_calls pc
on p.phone_number = pc.caller
) tt
left join people p
on tt.telefone = p.phone_number
where tt.caller_name = 'Pamela';

Related

SQL join To Fetch Mutiple Records

I need to find the firstName and Email address from of all teachers and parents in a single query
Here is the structure of the table :
// Patients Table
ID guid parentID PatientName
1 234 1258 John
2 xyz 111 Paul
// Patient_teacher table
ID PatiendGuid teacherid
1 122 132
2 xyz 1424
3 245 1545
4 xyz 1222
// Members table
ID guid email fname
22 123 hello#xyz.com hello
111 xyz parentEmail#xyz.com parentName
1424 343 teacherEmail#xyz.com teacherName
1222 546 teacher2EMail#xyz.com teacher2Name
And Here is the required Result:
//Required Result
fname Email
parentName parentEmail#xyz.com
techerName teacherEmail#xyz.com
teacher2Name teacher2Email#xyz.com
The problem is when I tried to search using join I found a single row that contains parentID and TeacherID
Here is what I tried:
select Members.email,Members.fname
from Members
join Patients on Members.guid = Patients.guid
join Patient_Teacher on Patient_Teacher.patientguid = Patients.guid
where patients.guid = 'xyz'
Here is the Solution :
select Members.id, Members.email, Members.fname
from Patients
join Patient_Teacher on Patient_Teacher.patientguid = Patients.guid
join Members on (Patient_Teacher.teacherid = Members.id
or Patients.parent = Members.id)
where patients.guid = 'xyz'
Have you checked the following reasons?
1- You have a table named 'Patients_teacher' but in your solution, you're referring to it as 'Patient_teacher'.
2- In 'Patients_teacher' table, you have a column named 'patiendguid' but in your solution you're referring to it as 'patientguid'.

exclude complete record if related table has a certain value

I have CLAIMMASTER table like this
CLAIMNO
123
456
789
and another related table PROCSTATUS like this
CLAIMNO PROCCODE
123 111
123 222
456 111
456 222
789 222
I want to exclude the records from table1 where proccode in table2 is 111
the result should be
CLAIMNO
789
I have tried almost everything i can but the closest result i get is like this
CLAIMNO PROCCODE
123 222
456 222
789 222
I know this should be easy but i can't figure out the query to do this.
please help.
Here is the query
select a.CLAIMNO,b.PROCCODE from dbo.CLAIMMASTER a left join
dbo.PROCSTATUS b on a.CLAIMNO = b.CLAIMNO
where a.CLAIMNO not in (select b.CLAIMNO where b.PROCCODE in ('111'))
If you only need to select claimno then no need to have join.
select a.CLAIMNO from dbo.CLAIMMASTER a
where a.CLAIMNO not in
(select distinct b.CLAIMNO from dbo.PROCSTATUS b where b.PROCCODE = '111')
Also if you have claimno repeated in the claimmaster table then you need to use distinct in the select clause.
select a.CLAIMNO
from dbo.CLAIMMASTER a
inner join dbo.PROCSTATUS b
on a.CLAIMNO = b.CLAIMNO
where a.CLAIMNO not in
(select CLAIMNO FROM dbo.PROCSTATUS where PROCCODE in ('111'))

Updating the first occurrence of the column with a value and the remaining with other value

select emp_id, emp_dept, emp_name
from employee
where emp_id in (123, 234);
emp_id emp_dept emp_name
*****************************
123 222 1234
123 222 5678
123 222 9101
234 222 1011
234 222 1112
234 222 1213
Here there are 3 records for each emp_id.
I want a query to update the emp_dept such that out of three records, only one record will be updated to 555(it can be any record doesnt matter) and the other 2 will be updated to 666.
Create a CTE (common table expression) adding a ROW_NUMBER window function partitioned by emp_id then write an update statement joining the cte and building a case statement to determine row number
The code below builds a Table Variable with Test data, selects the data to show you the "before" and then modifies with the cte method and selects the data to show you the final result.
;WITH cte AS (
SELECT
emp_id
,ROW_NUMBER() OVER (PARTITION BY emp_id ORDER BY emp_SSN) AS RowNum
FROM
#Table
)
UPDATE t
SET emp_dept = CASE WHEN RowNum = 1 THEN 555 ELSE 666 END
FROM
#Table t
INNER JOIN cte u
ON t.emp_id = u.emp_id
You can use MERGE.
Data Preparation
create table em1(
emp_id number, emp_dept number, emp_name varchar2(10));
insert into em1 values(123,1,'we');
insert into em1 values(123,1,'asd');
insert into em1 values(123,1,'rfw');
insert into em1 values(345,2,'rtg');
insert into em1 values(345,2,'bfg');
insert into em1 values(345,2,'uyi');
commit;
Query
MERGE INTO em1 e
USING (
SELECT emp_id, emp_dept, emp_name,
row_number() over (partition by emp_id order by 1) r
FROM em1
WHERE emp_id in (123,345)
) f
ON (f.emp_id = e.emp_id and f.emp_name = e.emp_name)
WHEN MATCHED THEN
UPDATE SET e.emp_dept = case when f.r = 1 then 555 else 666 end;
Result
emp_id emp_dept emp_name
-------------------------
123 555 we
123 666 asd
123 666 rfw
345 555 rtg
345 666 bfg
345 666 uyi

MSSQL join query with Group by

my table structure like this:
ID SID Type Description SN
82 372 PC XX 1234ZZ
83 372 Monitor YYY 2234ZZ
587 444 PC BBB 2255XX
588 444 Monitor CCC 4512XC
i would like to create a VIEW to show all record in same row group by SID (Staff ID)
my sql as follows:
SELECT DISTINCT a.SID,
CAST(b.Description AS NVARCHAR(100)) AS Name_PC,
CAST(b.SN AS NVARCHAR(100)) AS SN_PC,
CAST(c.Description AS NVARCHAR(100)) AS Name_Monitor,
CAST(c.SN AS NVARCHAR(100)) AS SN_Monitor,
dbo.StaffDB.DisplayName
FROM dbo.IT_Equ AS a INNER JOIN
dbo.StaffDB ON a.SID = dbo.StaffDB.SID LEFT OUTER JOIN
dbo.IT_Equ AS b ON a.SID = b.SID AND b.Type = 'PC' LEFT OUTER JOIN
dbo.IT_Equ AS c ON a.SID = c.SID AND c.Type = 'Monitor'
WHERE (b.Description IS NOT NULL) AND (b.SN IS NOT NULL)
AND (c.Description IS NOT NULL) AND (c.SN IS NOT NULL)
GROUP BY a.SID, CAST(b.Description AS NVARCHAR(100)),
CAST(b.SN AS NVARCHAR(100)),
CAST(c.Description AS NVARCHAR(100)),
CAST(c.SN AS NVARCHAR(100)),
StaffDB.DisplayName
the code works fine if staf only had one record for PC and monitor, it will show the following results:
SID Name_PC SN_PC Name_Monitor SN_Monitor DisplayName
372 XX 1234ZZ YYY 2234ZZ Peter
444 BBB 2255XX CCC 4512XC John
but if the staff had more than one PC record or monitor record, it will create duplicate records such as
original record in db:
ID SID Type Description SN
106 476 PC PC018 84TK5
107 476 Monitor LCD018 60P5D
421 476 PC PC220 85HYC
422 476 Monitor LCD220 51RMR
the result like this:
SID Name_PC SN_PC Name_Monitor SN_Monitor DisplayName
476 PC018 84TK5 LCD018 60P5D Mary
476 PC018 84TK5 LCD220 51RMR Mary
476 PC220 85HYC LCD018 60P5D Mary
476 PC220 85HYC LCD220 51RMR Mary
is it possible to enhance the query to become this ?
SID Name_PC SN_PC Name_Monitor SN_Monitor DisplayName
476 PC018 84TK5 LCD018 60P5D Mary
476 PC220 85HYC LCD220 51RMR Mary
thanks
Problem is in the data - you have to fix duplicates. Obviously 1 monitor belongs to 2 PCs -
PC018 - 60P5D and PC220 - 60P5D.
Alternatively you can try to arrange them and somehow to take 1st SN for the 1st PC and so on, but I don't think this is the right way.
how to you want to determine which sn_pc you want to use?
A distinct will not solve your problem, a distinct only eliminate identical lines.
You have to aggregate if it's possible : min(sn_pc)
You can use view function : row_number over (partition by sid, name_pc order by sn_pc) in a subquery then where rownum = 1
But when reading again the results, it seems you are missing a join criteria when joining your tables
dbo.IT_Equ AS c ON a.SID = c.SID AND c.Type = 'Monitor'
Here is the problem, use a subquery to only select the last line if possible.

t-sql update issue

tbl_indicator
grp_nbr, sect_nbr, indicat
001234 100 p
002345 101 s
tbl_group
grp_id, grp_nbr, sect_nbr, indicat
333 001987 100 a
555 001987 100 p
444 002987 101 s
222 02987 101 y
Here (in tbl_group) grp_id is the primary Key
tbl_order
order_id, grp_id
5000 333
5001 555
5002 555
5003 555
5004 444
5005 444
5006 222
In tbl_order, grp_id is a foreign Key to grp_id in tbl_group.
In table tbl_indicator, for one set of grp_nbr and sect_nbr there is an indicat, for the same set of grp_nbr and sect_nbr there is a correct indicat (555,1, 100, p) and a junk indicat (333, 1, 100, a) in table tbl_group, but both these grp_id (333, 555) are present in table tbl_orders.
And one more thing here is that the junk data (indicat) in group table (222, 02987, 101, y) the grp_nbr has one character length less than the grp_nbr in tbl_indicat. It should use something 'LIKE' operator
How can we handle this??
Now I need to update tbl_order table in such a way that the junk grp_id s should be replaced with correct grp_id s
The output should like:
tbl_orders
order_id, grp_id
5000 555
5001 555
5002 555
5003 555
5004 444
5005 444
5006 444
I already have answer if both the column data in tbl_indicat and tbl_grp tables are same...
It was answered by 'Dr. Wily's Apprentice'
sql update (help me )
but how to handle if the data is different (like missing some strings in starting)?
UPDATE o
SET o.grp_id = g2.grp_id
FROM tbl_order AS o
INNER JOIN tbl_group AS g1
ON g1.grp_id = o.grp_id
INNER JOIN tbl_group AS g2
ON g2.sect_nbr = g1.sect_nbr
AND g2.grp_nbr = '0' + g1.grp_nbr