SQL How to join two query's with different columns and joins - sql

I have 2 queries both use joins, select various columns from multiple tables which produce the below result sets:
companyID workType contractnumber employeenumber Value2
1 1C 9999999 111111 2547.21
1 1C 9999999 222222 863.67
1 1C 9999999 333333 2962.15
1 1C 9999999 444444 1971.61
1 1C 9999999 555555 152.41
1 1C 9999999 666666 155.90
1 1C 9999999 777777 657.20
companyID normalWorkType employeeNumber value1
1 1C 11111 1016.08
1 1C 22222 3118.05
1 1C 33333 2628.81
1 61 44444 2547.21
I'm looking to join these to produce the below result.. can anyone explain what the correct syntax would be?
companyID normalWorkType contractnumber employeeNumber value1 Value2
1 1C 9999999 11111 1016.08 2547.21
1 1C 9999999 22222 3118.05 863.67
1 1C 9999999 33333 2628.81 2962.15
1 61 9999999 44444 2547.21 1971.61
1 1C 9999999 55555 0 152.41
1 1C 9999999 66666 0 155.90
1 1C 9999999 77777 0 657.20
Grouping above is on companyID & employeeNumber

Try LEFT OUTER JOIN:
SELECT t1.companyID,
t2.normalWorkType,
t1.contractnumber,
t1.employeeNumber,
coalesce(t2.value1,0) as t2.value1,
t1.value2
FROM DatabaseName.t1 AS t1 LEFT OUTER JOIN
DatabaseName.t2 AS t2 ON t1.employeenumber = t2.employeenumber
AND t1.companyID = t2.companyID

I'm assuming here that the contract numbers in the proposed result set are actually the contract numbers from your first query, and that the difference is just a typo. If that's true, this will get you what you want.
SELECT
q1.companyID
COALESCE(q2.normalWorkType,q1.workType) AS normalWorkType
q1.contractnumber
q1.employeeNumber
COALESCE(q2.value1 ,0) as value1
q1.Value2
FROM
(
<Your first query>
) as q1
LEFT JOIN
(
<Your second query>
) as q2
ON
q1.companyID = q2.companyID
AND
q1.employeeNumber = q2.employeeNumber;

Try below Query
select Table1.companyId,Table2.normalworktype,Table1.contractnumber,
Table1.employeenumber,Table2.value1,Table1.value2
from Table1
inner join Table2 on Table1.companyid = Table2.companyid
and Table1.employeeNumber=Table2.employeeNumber

Thanks for the responses everyone,
After trying Husam Ebish's suggestion It wasn't quite what I needed but lead me to this thread. (up-voted your answer)
How to combine two query results into one and I have different column name
What I really found useful was this bit of information highlighted below from the linked thread. After trying the different "left" joins suggested the comment's highlighted lead me to try "full outer join" which has given me the correct result-set.
If you only have one row from each query, it's just a CROSS JOIN
SELECT
*
FROM
(query1) AS q1
CROSS JOIN
(query2) AS q2
If you have more than one row from each query, you need an INNER JOIN
or maybe a FULL OUTER JOIN and some relationship between the two sets
of data
SELECT
*
FROM
(query1) AS q1
FULL OUTER JOIN
(query2) AS q2
ON q2.id2 = q1.id1
Note:
UNION appends data vertically
JOIN appends data horizontally

SELECT
*
FROM
(select top 1 VL1,VL2,VL3 from current_voltage AS q1
where deviceimei ='233'
order by devicetimestamp) AS q1
CROSS JOIN
(select top 1 OTI,WTI,ATI from overview AS q2
where deviceimei ='233'
order by devicetimestamp ) AS q2

You can put your search result to 2 temp table and then join this 2 temp table or use alliance for your each select and then join them.
like :
SELECT
*
FROM (
SELECT
companyID
,workType
,contractnumber
,employeenumber
,Value2
FROM table1
) t1
INNER JOIN (
SELECT
companyID
,normalWorkType
,contractnumber
,employeeNumber
,value1
,Value2
FROM table2
) t2
ON t1.companyID = t2.companyid
or put your result 2 different temp table and then join them
SELECT
companyID
,workType
,contractnumber
,employeenumber
,Value2
INTO #tt1
FROM table1
SELECT
companyID
,normalWorkType
,contractnumber
,employeeNumber
,value1
,Value2
INTO #tt2
FROM table2
SELECT *
FROM #tt1 t1
INNER JOIN #tt2 t2 ON t1.companyid = t2.companyID

Related

Joining table get the first data on first table if duplicate

Hi i have table1 and table2.
table1 is the logtime table of employees and table2 is the groupcode of the employee.
On table1 some employees has duplicate time in because they time in multiple time to just to secure their time in.
Table1
ID EMPID Time_IN
1 001 7:01 AM
2 004 7:04 AM
3 034 7:10 AM
4 034 7:11 AM
5 019 7:11 AM
6 019 7:12 AM
Table2
ID empID GroupName
1 001 AA
2 004 AB
3 034 AA
4 019 AA
result
GroupName CNT
AA 5
AB 1
Expected result
GroupName CNT
AA 3
AB 1
current query
Select b.GroupName, count(*) as cnt
from table1 a
inner join table2 b
on a.EMPID = b.empID
Group by b.GroupName
How can i achive as expected result above?
Thankyou in advance.
you can use distinct count as follows:
select t2.groupname, count(distinct empid) as cnt
from table1 t1 join table2 t2
on t1.empid = t2.empid
group by t2.groupname
The join is superfluous for the question you have asked:
select t2.GroupName, count(*) as cnt
from table2 t2
group by t2.GroupName;
This is much more efficient than joining and using count(distinct). You probably really have a different question, which should be asked as a new question.

Using Group By as part of a where clause

I'm trying to eliminate certain records from a dataset using SQL Server. The title of my post may be inaccurate, as a better solution may exist than what I have in mind.
In my query, I am selecting from Table A, and the rows that I want to end up with should meet the following criteria:
All rows where A.ItemNumber = B.ItemNumber
All rows where A.ItemNumber <> B.ItemNumber AND that row's Task value does not have another row that meets criteria #1.
So for the below example:
Gives us ItemNumber 102, 104, 106 rows.
Gives us ItemNumber 105 row.
100, 101 are removed from dataset because their Task (1) is associated with Table B at ItemNumber 102. Same for 103 with Task (2) being associated at ItemNumber 104.
Table A
Task ItemNumber
1 100
1 101
1 102
2 103
2 104
3 105
4 106
Table B
ItemNumber Data
102 aaa
104 bbb
106 ccc
My initial thought was to load Table A into a temp table, LEFT JOIN with Table B, and DELETE FROM {temp table} WHERE (data IS NULL AND {insert some kind of grouping logic here}). But I have been completely unable to figure out a grouping logic that will work for the problem. I spent the weekend hoping a solution would come to me, but am now giving in and seeking advice.
With a CTE that meets the 1st condition and UNION ALL to return the rest of the rows:
with cte as (
select a.*
from TableA a
where exists (select 1 from TableB where ItemNumber = a.ItemNumber)
)
select * from cte
union all
select a.* from TableA a
where not exists (select 1 from cte where Task = a.Task)
order by Task
See the demo.
Results:
Task ItemNumber
1 102
2 104
3 105
4 106
One way to phrase this puts all the filtering logic in the where clause:
select a.*
from tablea a
where exists (select 1
from tableb b
where b.itemnumber = a.itemnumber
) or
not exists (select 1
from tableb b2 join
tablea a2
on b2.itemnumber = a2.itemnumber
where a2.task = a.task
);
SELECT *
FROM TABLEA AS A
LEFT JOIN TABLEB AS B ON A.ItemNumber = B.ItemNumber
WHERE B.ItemNumber IS NOT NULL -- critera 1
OR (B.ItemNumber IS NULL AND B.ItemNumber NOT IN
(SELECT A.ItemNumber
FROM TABLEA AS A
JOIN TABLEB AS B ON A.ItemNumber = B.ItemNumber)) -- criteria 2

Merge two tables by two variables in SQL Server

I have two tables that I want to merge by the two common variables.
So I have
Table1
Var1 Var2 Dates
---------- ---------- ----------------------
111111 AA 1990-06-20
111111 AA 2000-06-20
222222 BB 1963-06-20
222222 BB 2005-06-20
333333 CC 2006-06-30
333333 CC 2016-06-26
and Table2
Var2 Dates
---------- ----------------------
AA 1990-06-20
BB 1963-06-20
I want the output to be
Var1 Var2 Dates
---------- ---------- ----------------------
111111 AA 1990-06-20
222222 BB 1963-06-20
I have tried inner join two times using "Var2" and "Dates" in two tables. But the results gave me more rows (duplicate entries) than I need.
Well, the most common way would be to use an INNER JOIN:
SELECT T1.*
FROM Table1 T1
INNER JOIN Table2 T2
ON T1.Var1 = T2.Var1
AND T1.Dates = T2.Dates
But this makes more sense when you also want to use some columns from the second table. In your case, you could do just:
SELECT *
FROM Table1 T1
WHERE EXISTS(SELECT 1 FROM Table2
WHERE Var1 = T1.Var1
AND Dates = T1.Dates)
I think in your case you need only one JOIN with multiple conditions
SELECT t1.*
FROM Table1 t1
JOIN Table2 t2 ON t1.Var2 = t2.Var2 AND t1.Dates = t2.Dates

How can I avoiding Cartesian product on SQL on multiple tables

Here is my sqlfiddle http://sqlfiddle.com/#!3/671c8/1.
Here are my tables:
Person
PID LNAME FNAME
1 Bob Joe
2 Smith John
3 Johnson Jake
4 Doe Jane
Table1
PID VALUE
1 3
1 5
1 35
2 10
2 15
3 8
Table2
PID VALUE
1 X1
1 X2
1 X3
2 Z1
3 X3
I am trying to join several tables on a person's ID. These tables contain events with dates, but the dates may or may not match across table. So what I really want it to regardless of date join the tables in a way such that when I get results the table with the largest rows will be the amount of rows in my result and all other tables will "fit" within. For example
Instead of this which is a cartesian product:
PID LNAME FNAME THINGONE THINGTWO
1 Bob Joe 3 X1
1 Bob Joe 3 X2
1 Bob Joe 3 X3
1 Bob Joe 5 X1
1 Bob Joe 5 X2
1 Bob Joe 5 X3
1 Bob Joe 35 X1
1 Bob Joe 35 X2
1 Bob Joe 35 X3
I would like something like this:
PID LNAME FNAME THINGONE THINGTWO
1 Bob Joe 3 X1
1 Bob Joe 5 X2
1 Bob Joe 35 X3
My sql statement:
SELECT
p.*,
t1.value as thingone,
t2.value as thingtwo
FROM
person p
left outer join table1 t1 on p.pid=t1.pid
left outer join table2 t2 on p.pid=t2.pid
;
I can't fathom why you want to do this, but...
You need to create an artificial join between table1 and table2, and then link that to the master table. One way of doing that is by ranking the rows in order. eg:
SELECT
p.pid, p.lname,p.fname, thingone, thingtwo
FROM
person p
left outer join
(
select ISNULL(t1.pid, t2.pid) as pid, t1.value as thingone, t2.value as thingtwo
from
(select *, ROW_NUMBER() over (partition by pid order by value) rn
from table1) t1
full outer join
(select *, ROW_NUMBER() over (partition by pid order by value) rn
from table2) t2
on t1.pid=t2.pid and t1.rn=t2.rn
) v
on p.pid = v.pid
This is a trickier problem than I thought. The challenge is being sure that all the records appear, regardless of the lengths of the two lists. The following works by enumerating each of the lists and using that for the join conditions:
SELECT p.*,
t1.value as thingone,
t2.value as thingtwo
FROM person p left outer join
(select t1.*,
row_number() over (partition by pid order by pid) as seqnum,
count(*) over (partition by pid) as cnt
from table1 t1
) t1
on p.pid = t1.pid left outer join
(select t2.*, row_number() over (partition by pid order by pid) as seqnum,
count(*) over (partition by pid) as cnt
from table2 t2
) t2
on p.pid = t2.pid
WHERE t1.seqnum = t2.seqnum or
(t2.seqnum > t1.cnt) or
(t1.seqnum > t2.cnt) or
t1.seqnum is null or
t2.seqnum is null;
Here is a slight modification to your SQL Fiddle that has better test data.
EDIT:
The logic in the where clause handles these cases (in order by the clauses):
Where the two lists have sequence numbers, these must match.
Where list2 is longer and list1 has at least one element.
Where list1 is longer and list2 has at least one element.
Where list1 is empty
Where list 2 is empty
These were arrived at by trial and error, because the original condition did not work:
on p.pid = t2.pid and t1.seqnum = t2.seqnum
This returns NULL values for p.id for the extra elements on the list. Podliuska's approach may also work; I had just started down this path and the where conditions do the trick.

MSSQL select single row with all references counted

I am attempting to do something using MSSQL that I believe is possible (easily) but I do not know how to vocalize the correct search string. I have the situation below.
Table A
UID | Value....
1 | a
2 | b
3 | c
Table B
PartTypes_uid_fk | Value....
1 | a
1 | b
1 | c
1 | d
1 | e
3 | 67
3 | 1354
I am attempting to get the following result, query Table A for all results {TableA.*} and on the same row result show the number of table b references {count TableB.tableA_fk}
What I have so far is the following.
SELECT DISTINCT t1.uid, CONVERT(varchar(MAX), t1.Name) AS Name, CONVERT(varchar(MAX), t1.Description) AS Description,
Count(t2.Items_uid_fk) OVER (Partition By t2.PartTypes_uid_fk) as Count
FROM [Table1] as t1 left outer join Table2 as t2 on t2.PartTypes_uid_fk=t1.uid;
This works for all of Table A records with an associated record in Table B but if there are 0 entries in Table B it won't work. The conversion of the varchars was required due to the fact they are ntext format and it was distinct.
Thank you for all your help in advance.
Stephen
Instead of running into problems with the GROUP BY on N/TEXT columns, and to run faster, you would want to pre-aggregate the B table and LEFT JOIN that against A.
select t1.*, ISNULL(t2.c, 0) AS CountOfB
from table1 t1
left join
(
select parttypes_uid_fk, count(*) c
from table2
group by parttypes_uid_fk
) t2 on t2.PartTypes_uid_fk=t1.uid
It's easier than that:
SELECT t1.uid, t1.Name, COUNT(*)
FROM [Table1] t1
LEFT JOIN [Table2] t2 ON t2.PartTypes_uid_fk = t1.uid
GROUP BY t1.uid, t1.Name
Your query should be
SELECT t1.uid,
CONVERT(varchar(MAX), t1.Name) AS Name,
CONVERT(varchar(MAX), t1.Description) AS Description,
Count(t2.Items_uid_fk) CountItems
FROM [Table1] as t1 left outer join Table2 as t2 on t1.uid = t2.PartTypes_uid_fk
GROUP BY uid, t1.name, t1.Description;