Combining 3 separate sql queries into one result - sql

So I have three sql queries requesting 3 different things
but I want to be able to combine them into 1 table so that each query appears in each column
these are the queries:
select b.name, count(*)
from account a join branch b
on a.open_branch_id = b.branch_id
group by b.name;
select b.name, count(*)
from employee e join branch b
on e.assigned_branch_id = b.branch_id
group by b.name;
select b.name, count(*)
from customer c join branch b
on c.city = b.city
group by b.name;
i don't know how to combine them so query 1 will appear in 1 column, query 2 in the 2nd column, and query 3 in the third column.
Anyone have any ideas?
Thanks

If the name column is going to have the same values, you can join them like this. From your query however, it seems that the names you are showing are of branches, employees and customers.
select b.name as Name, count(*) as [Count] into #Result1 from account a join branch b on a.open_branch_id = b.branch_id group by b.name;
select b.name as Name, count(*) as [Count] into #Result2 from employee e join branch b on e.assigned_branch_id = b.branch_id group by b.name;
select b.name as Name, count(*) as [Count] into #Result3 from customer c join branch b on c.city = b.city group by b.name;
select r1.name,
r1.[Count],
r2.[Count],
r3.[Count],
from #Result1 as r1
left join #Result2 as r2 on r1.name = r2.name
left join #Result3 as r3 on r1.name = r3.name
drop table #Result1
drop table #Result2
drop table #Result3

If I'm understanding your question, you want to join your results based on your name field from each query? Assuming each have the same names, you can do this with JOINs and subqueries. Here is a simplified version (replace the subqueries with yours above):
select t1.name, t1.cnt,
t2.name as t2name, t2.cnt as t2cnt,
t3.name as t3name, t3.cnt as t3cnt
from
(select name, count(1) cnt
from t1
group by name) t1 join
(select name, count(1) cnt
from t2
group by name) t2 on t1.name = t2.name join
(select name, count(1) cnt
from t3
group by name) t3 on t1.name = t3.name
SQL Fiddle Demo
Edit, given your comments, it appears this is what you might be looking for:
select b.name,
a.acctcnt, e.empcnt, c.citycnt
from branch b
left join (
select count(1) acctcnt, open_branch_id
from account
group by open_branch_id
) a on a.open_branch_id = b.branch_id
left join (
select count(1) empcnt, assigned_branch_id
from employee
group by assigned_branch_id
) e on e.assigned_branch_id = b.branch_id
left join (
select count(1) citycnt, city
from customer
group by city
) c on c.city = b.city
More Fiddle

You could do it like this (SQL Server 2005 and up):
SELECT
B.Name,
B.OtherColumnsIfYouLike,
ACount = IsNull(ACount, 0),
ECount = IsNull(E.ECount, 0),
CCount = IsNull(C.CCount, 0)
FROM
dbo.Branch B
OUTER APPLY (
SELECT ACount = Count(*)
FROM dbo.Account A
WHERE B.Branch_ID = A.Open_Branch_ID
) A
OUTER APPLY (
SELECT ECount = Count(*)
FROM dbo.Employee E
WHERE B.Branch_ID = E.Assigned_Branch_ID
) E
OUTER APPLY (
SELECT CCount = Count(*)
FROM dbo.Customer C
WHERE B.City = C.City
) C
;
Any query you use needs to pay attention to whether there may be no results at all for that branch name. Using INNER JOIN (or just JOIN) will exclude these instead of properly showing 0.
Using your existing queries intact will work like the following, but won't perform as well:
SELECT
Name = Coalesce(A.Name, E.Name, C.Name),
ACount = IsNull(ACount, 0),
ECount = IsNull(E.ECount, 0),
CCount = IsNull(C.CCount, 0)
FROM
(
select b.name, ACount = Count(*)
from account a join branch b on a.open_branch_id = b.branch_id
group by b.name
) A
FULL JOIN (
select b.name, ECount = Count(*)
from employee e join branch b on e.assigned_branch_id = b.branch_id
group by b.name
) E ON A.Name = E.Name
FULL JOIN (
select b.name, CCount = Count(*)
from customer c join branch b on c.city = b.city group by b.name
) C ON IsNull(A.Name, E.Name) = C.Name
;

I think this is the fastest:
with a as
(
select open_branch_id as b_id, count(*) as a_count
from account a
group by open_branch_id
), e as
(
select assigned_branch_id as b_id, count(*) as e_count
from employee e
group by assigned_branch_id
), c as
(
select b.branch_id as b_id, count(*) as c_count
from customer c join branch b
on c.city = b.city
group by b.name
)
select b.name, a.a_count, e.e_count, c.c_count
from branch b
left join a on a.b_id = b.branch_id
left join e on e.b_id = b.branch_id
left join c on c.b_id = b.branch_id
order by b.name

Related

How to subtract values from different tables?

I need to get the result of subtract values from these 3 different tables in SQL Server.
This is my SQL:
SELECT COUNT(A.Id)
FROM Table_A AS A WITH (NOLOCK)
WHERE A.City = 'NewYork'
SELECT COUNT(B.Id)
FROM Table_B AS B WITH (NOLOCK)
WHERE B.City = 'England'
SELECT COUNT(C.Id)
FROM Table_C AS C WITH (NOLOCK)
WHERE C.City = 'Berlin'
Let's say the result of the first query is 9, and the second one is 1, and the third one is 3.
I need to get (9-1-3 = 5). How can I do this?
You can do this with a CTE or with subqueries.
Using a CTE:
WITH tbla AS (
SELECT COUNT(A.Id) A
FROM Table_A AS A
WHERE A.City = 'NewYork'
),
tblb AS (
SELECT COUNT(B.Id) B
FROM Table_B AS B
WHERE B.City = 'England'
),
tblc AS (
SELECT COUNT(C.Id) C
FROM Table_C AS C
WHERE C.City = 'Berlin'
)
SELECT a.A - b.B - c.C
FROM tbla a
CROSS JOIN tblb b
CROSS JOIN tblc c;
Same thing only with subqueries
SELECT a.A - b.B - c.C
FROM (
SELECT COUNT(A.Id) A
FROM Table_A AS A
WHERE A.City = 'NewYork'
) a
CROSS JOIN (
SELECT COUNT(B.Id) B
FROM Table_B AS B
WHERE B.City = 'England'
) b
CROSS JOIN (
SELECT COUNT(C.Id) C
FROM Table_C AS C
WHERE C.City = 'Berlin'
) c;
Note: I removed the WITH (NOLOCK) hints because in all likelihood they are not needed in this case.
As all queries return a scalar value 8one row one column you can simply add or subtract them
SELECT
(SELECT
COUNT(A.Id)
FROM
Table_A AS A
WHERE
A.City = 'NewYork') - (SELECT
COUNT(B.Id)
FROM
Table_B AS B
WHERE
B.City = 'England') - (SELECT
COUNT(C.Id)
FROM
Table_C AS C
WHERE
C.City = 'Berlin') as Whatever

SQL Query Join two Queries with Sum()

I know this is simple for you sql people, but I am trying to combine two simple queries into one. It's probably obvious from the code that job.ActiveJob.ID = job.EstimateTbl.ID_Job.
I'm trying to get: id, JobName, sum(itemAmount)
Thanks for your help.
SELECT a.id, a.JobName
FROM job.ActiveJobsTbl AS a
WHERE a.ID = '100'
SELECT SUM(itemAmount)
FROM job.EstimateTbl
WHERE ID_Job = '100'
You can JOIN the tables by the ON E.ID_Job = A.ID and get the values in SELECT with GROUP BY
SELECT A.id, A.JobName, SUM(E.itemAmount) AS Amount
FROM job.ActiveJobsTbl AS A
INNER JOIN job.EstimateTbl E ON E.ID_Job = A.ID
WHERE A.ID = '100'
GROUP BY A.id, A.JobName;
using LEFT JOIN
SELECT a.id, a.JobName,EstimateTbl.itemAmount
FROM job.ActiveJobsTbl AS a
left join
(
SELECT SUM(itemAmount) itemAmount,ID_Job
FROM job.EstimateTbl
group by ID_Job
) EstimateTbl on EstimateTbl.ID_Job = a.ID
WHERE a.ID = '100'
You can use APPLY :
select a.id, a.JobName, t.itemAmount
from job.ActiveJobsTbl AS a OUTER APPLY
(SELECT SUM(t.itemAmount) AS itemAmount
FROM job.EstimateTbl AS t
WHERE t.ID_Job = a.ID
) t
WHERE a.ID = 100;
Try this:
SELECT A.id, A.JobName, SUM(E.itemAmount) AS Amount
FROM job.ActiveJobsTbl AS A
INNER JOIN job.EstimateTbl E ON E.ID_Job = A.ID
WHERE A.ID = '100'
GROUP BY A.id, A.JobName;

How GROUP BY with two inner join in postgresql

I am new in SQL, I have a basic question. I have 3 tables and 2 inner joins.
This is my SQL code:
select c.name, case when e.time > NOW() then 'Yes' else 'No' end AS "time"
from table1 as e
INNER JOIN table2 as a on e.id = a.id
INNER JOIN table3 as c on a.id = c.id
where e.conty= 'SAD'
GROUP BY c.name;
Error: must appear in the GROUP BY clause or be used in an aggregate function
Any field you want to retrieve must be contained in the GROUP BY clause of that query. You should include "time" in the GROUP BY clause or exclude it from the query.
select c.name, case when e.time > NOW() then 'Yes' else 'No' end AS "time"
from table1 as e
INNER JOIN table2 as a on e.id = a.id
INNER JOIN table3 as c on a.id = c.id
where e.name = 'JOHN'
GROUP BY c.name, time;
Use the e.time attribute in the GROUP BY clause.
select c.name, case when e.time > NOW() then 'Yes' else 'No' end AS "time"
from table1 as e
INNER JOIN table2 as a on e.id = a.id
INNER JOIN table3 as c on a.id = c.id
where e.name = 'JOHN'
GROUP BY c.name, e.time;
I am guessing that you want aggregation -- and the maximum time:
select c.name,
(case when max(e.time) > NOW() then 'Yes' else 'No' end) AS "time"
from table1 e join
table2 a
on e.id = a.id join
table3 c
on a.id = c.id
where e.name = 'JOHN'
group by c.name;
You don't need to group by name since you select only the rows with name = 'JOHN'.
If you want to select the row with the maximum time, do this:
select
'JOHN' name,
case when max(e.time) > NOW() then 'Yes' else 'No' end AS "time"
from table1 as e
INNER JOIN table2 as a on e.id = a.id
INNER JOIN table3 as c on a.id = c.id
where e.name = 'JOHN'

How to get only unique row result

I have complex join query ,
Select a.date, b.Name, d.description
FROM tableA as a
INNER JOIN (SELECT Name, MAX(Time) as lastSentTime FROM tableA
GROUP BY Name) b ON a.Name = omh.Name AND b.lastSentTime = b.setTime
INNER JOIN tableD as d ON d.Id = a.id
INNER JOIN tableE as e ON e.Id = d.id
INNER JOIN tableF as f ON f.Id = a.id
WHERE a.status = 'FAILED' AND a.Class = 'Secondary' AND a.marks = e.marks
which will return data as
Date Name Discription
1/2/16 Test I am testing
1/2/16 Test I am testing
1/2/16 Test1 I am testing1
1/2/16 Test1 I am testing1
I need result as
Date Name Discription
1/2/16 Test I am testing
1/2/16 Test1 I am testing1
Try DISTINCT
Select DISTINCT a.date, b.Name, d.description
FROM tableA as a
INNER JOIN (SELECT Name, MAX(Time) as lastSentTime FROM tableA
GROUP BY Name) b ON a.Name = omh.Name AND b.lastSentTime = b.setTime
INNER JOIN tableD as d ON d.Id = a.id
INNER JOIN tableE as e ON e.Id = d.id
INNER JOIN tableF as f ON f.Id = a.id
WHERE a.status = 'FAILED' AND a.Class = 'Secondary' AND a.marks = e.marks
Maybe an entirely different approach is what you need. The join to the subquery seems very strange. Also one of your join predicates was in there where clause instead of the join.
with SortedResults as
(
Select a.date
, b.Name
, d.description
, ROW_NUMBER() over(partition by b.Name order by a.date desc) as RowNum
FROM tableA as a
INNER JOIN tableD as d ON d.Id = a.id
INNER JOIN tableE as e ON e.Id = d.id AND a.marks = e.marks
INNER JOIN tableF as f ON f.Id = a.id
WHERE a.status = 'FAILED'
AND a.Class = 'Secondary'
)
select date
, Name
, description
from SortedResults
where RowNum = 1

SQL Select MAX w/ Left Join

SELECT a.first, a.last, b.number, c.last_login
FROM Table1 a
LEFT JOIN Table2 b ON a.first = b.first AND a.last = b.last
LEFT JOIN Table3 c ON b.number = c.number
Sometimes their are multiple entries for the number and I need to only select the max number from table b, however, when i try
SELECT a.first, a.last, MAX(b.number), c.last_login
I get an error. What can I do to select the maximum b.number?
EDIT : Many years I haven't done SQLServer, but maybe the Analytic function can do the trick
SELECT v.first, v.last, c.number, c.last_login
FROM (
SELECT a.first, a.last, LAST_VALUE(b.number) OVER (PARTITION BY a.first, a.last ORDER BY a.first, a.last, b.number) AS yourmax
FROM Table1 a
LEFT JOIN Table2 b ON a.first = b.first AND a.last = b.last
GROUP BY a.first, a.last
) v
INNER JOIN Table3 c ON v.yourmax = c.number
Can you confirm this? I haven't sqlserver, but on oracle the MAX() OVER (...) exists.
LAST_VALUE isn't the only keyword applying to OVER analitics
If you want the max number you can use
SELECT a.first, a.last, b.MaxNumber, c.last_login
FROM Table1 a
LEFT JOIN (select tmp.first, tmp.last, max(tmp.number) MaxNumber from Table2 tmp
group by tmp.first, tmp.last
) b
ON a.first = b.first AND a.last = b.last
LEFT JOIN Table3 c ON b.MaxNumber = c.number