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
Related
I'm trying to rewrite a select from multiple tables into a series of joins. I thought my solution would be equivalent but it's not returning the same data. An ideas? Here's the code:
/* without joins:*/
SELECT
A.column3,
D.column6,
E.column2,
I.column2,
E.column3,
F.column1,
G.column2
FROM table1 A, table2 B, table3 C, table4 D, table5 E, table6 F, table7 G table8 H
LEFT OUTER JOIN table9 I ON H.ID = I.ID
WHERE
A.ID = C.ID
B.ID = C.ID
D.ID = B.ID
D.ID = E.ID
E.ID = F.ID
F.ID = G.ID
E.ID = H.ID
AND H.ISDELETED<>'T'
AND D.ISDELETED<> 'T'
/* Here's my attempt to turn it into at series of joins: */
SELECT
D.column3,
E.column6,
I.column2,
E.column2,
F.column3,
G.column1
FROM table1 A
JOIN table3 C ON A.ID = C.ID
JOIN table2 B ON B.ID = C.ID
JOIN table4 D ON D.ID = B.ID
JOIN table5 E ON D.ID = E.ID
JOIN table6 F ON E.ID = F.ID
JOIN table7 G ON F.ID = G.ID
JOIN table8 H ON E.ID = H.ID
LEFT OUTER JOIN table9 I ON H.ID = I.ID
WHERE G.ISDELETED<>'T'
AND E.ISDELETED<> 'T'
Change your query with the JOIN's to this and see if it matches up with your initial query:
SELECT
A.column3,
D.column6,
E.column2,
I.column2,
E.column3,
F.column1,
G.column2
FROM table1 A
INNER JOIN table2 B ON A.ID = C.ID
INNER JOIN table3 C ON B.ID = C.ID
INNER JOIN table4 D ON D.ID = B.ID
INNER JOIN table5 E ON D.ID = E.ID
INNER JOIN table6 F ON E.ID = F.ID
INNER JOIN table7 G ON F.ID = G.ID
INNER JOIN table8 H ON E.ID = H.ID
LEFT OUTER JOIN table9 I ON H.ID = I.ID
WHERE
AND H.ISDELETED<>'T'
AND D.ISDELETED<> 'T'
Your aliases do not match between the two queries which may throw off the results of the JOIN.
Also, in your first query your WHERE clause is:
AND table8.ISDELETED<>'T'
AND table4.ISDELETED<> 'T'
In your bottom query, your WHERE clause is:
AND table7.ISDELETED<>'T'
AND table5.ISDELETED<> 'T'
Which may also lead to difference results between the two.
I need to concatinate results from 2 tables without using UNION.
Ex : I have 4 tables a, b, c, d. see below snips:
Table a:
Table b:
Table c:
Table d:
I am concatinating a and d results using UNION ALL like below:
select a.id,a.seq,a.item,b.des,c.qty from a
left join b on a.item = b.item
left join c on a.id = c.id and a.seq = c.seq
UNION ALL
select d.id,d.seq,d.item,d.des,c.qty from d
join c on d.id = c.id and d.seq = c.seq
My output:
But I need same result without using UNION ALL.
Is it possible if so HOW?
You can apply Full Outer join instead of Union which has its similarities to Union
SELECT a.id,a.seq,a.item,b.des,c.qty
FROM a left join b on a.item = b.item
left join c on a.id = c.id and a.seq = c.seq
FULL OUTER JOIN
(
SELECT d.id,d.seq,d.item,d.des,c.qty
FROM d join c on d.id = c.id and d.seq = c.seq
)x ON a.id = x.id
You can replace union all with full join with a "false" condition and lots of COALESCE()s.
The logic looks like this:
SELECT COALESCE(abc.id, cd.id) as id,
COALESCE(abc.seq, cd.seq) as seq,
COALESCE(abc.item, cd.item) as item,
COALESCE(abc.des, cd.des) as eesc,
COALESCE(abc.qty, cd.qty) as qty
FROM (SELECT a.id, a.seq, a.item, b.des, c.qty
FROM a LEFT JOIN
b
ON a.item = b.item LEFT JOIN
c
ON a.id = c.id AND a.seq = c.seq
) abc FULL JOIN
(SELECT d.id, d.seq, d.item, d.des, c.qty
FROM d JOIN
c
ON d.id = c.id AND d.seq = c.seq
) dc
ON 1 = 0; -- never evaluates to true
There is a LEFT JOIN from table 'a' to table 'c' (on 'id' and 'seq' columns) in the upper query and INNER JOIN from table 'd' to table 'c' in the lower query. Therefore I think you could LEFT JOIN from table 'c' to table 'd' and it would produce the correct output.
select a.id,a.seq,a.item,b.des,c.qty
from a
left join b on a.item = b.item
left join c on a.id = c.id and a.seq = c.seq
left join d on c.id = d.id and c.seq = d.seq;
If you want you can use INSERT INTO a (tmp) table and get the same result in a table.
I've below query, into which I'm creating using a subquery which is returning
ORA-01427: single-row subquery returns more than one-row error.
But I want all the values that subquery is returning, and there is no other column left for the join condition. Below is my sample query.
select name,
dob,
cdate,
(select value
from item a,
books b
where a.id = b.id
and a.newid = b.newid
and a.id = s.id
and a.bid = s.cid
and a.eventid=1) col_value,
(select value2
from item a,
books b
where a.id = b.id
and a.newid = b.newid
and a.id = s.id
and a.bid = s.cid
and a.eventid=1) col_value2
from sample s,
purchase p
where s.id = p.id
and s.cid = p.cid
Desired Output
Do I need to apply a Group By? Please let me know your suggestions.
It is little bit more difficult without data but try:
select name -- please use table alias so you know which table the value is from (s, p or cv)
, dob
, cdate
, cv.value
from sample s
left join purchase p on s.id=p.id and s.cid=p.cid --or just join
left join (select value, a.id, a.bid --or just join
from item a
left join books b --or just join
on a.id=b.id and a.newid=b.newid) cv
on cv.id = s.id and cv.bid = s.cid
left join (select value2
from item a
left join books b
on a.id = b.id and a.newid = b.newid) cv2
on cv2.id = s.id and cv2.bid = s.cid
where cv2.eventid=1;
select name,
dob,
cdate,
(select value
from
books b
where a.id = b.id
and a.newid = b.newid ) col_value,
(select value2
from
books b
where a.id = b.id
and a.newid = b.newid ) col_value2
from sample s,
purchase p,item a
where s.id = p.id
and s.cid = p.cid
and a.id(+)=s.id
and a.bid(+)=s.cid
and a.eventid(+)=1
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
I want to find duplicate phones in TableC (batch 82) but phone is stored in TableD
I need to compare tablec against itself while getting the phone from tabled
Any ideas on how to go about this are appreciated?
SELECT *
FROM (SELECT d.phone,
d.id
FROM tablec c
JOIN tabled d
ON c.tableid = d.id
WHERE c.batch = 82) d
JOIN (SELECT d.phone,
d.id
FROM tablec c
JOIN tabled d
ON c.tableid = d.id
WHERE c.batch = 82) c
ON d.phone = c.phone
WHERE d.id < c.id
SELECT d.phone,
MIN(d.id) MINID, MAX(d.id) MAXID , COUNT(*) COUNT
FROM tablec c
JOIN tabled d
ON c.tableid = d.id
WHERE c.leadlistid = 81
GROUP BY d.phone
HAVING COUNT(*)> 1
SELECT
d.phone,
count(c.phone)
FROM
tableD d
LEFT JOIN tableC c
ON d.id = c.tableID
/* not sure what you mean by batch 82 -- maybe this: (?)
WHERE
c.batch = 82
*/
GROUP BY
d.phone
HAVING
count(c.phone) > 1