I have two sets A and B. I want to display counts of A as well as counts on A (intersection) B using condition X.
Code I am using
SELECT COUNT(A) as total, COUNT(IF (condition_X)) as chg
FROM A
FULL OUTER JOIN B
ON JOIN KEY Y
I am able to get the intersection but not the count of A in total.
Perhaps you just want a cross join?
select *
from (select count(*) as cnt_a from a) a cross join
(select count(*) as cnt_b
from a join
b
on y
where condition
) b
Simply left join the two
Select count(A.id=B.id),
count(A.id)
from A left join B on A.id=B.id
where condition='x'
Related
I want to sum two tables. Both tables contain the number of rowas grouped by a category:
number category
5 A
4819 B
1 C
number category
12043 B
I tried the following:
select a.category, a.number + b.number as number
from a
right join b
on a.category = b.category
I get:
number category
4 16862
I don't understand why I don't get all three categories. I trief left join instead of right join.
The problem with you right join is that a table should appear on the right side of the join. Or, using a left join, we could write:
SELECT
a.category,
a.number + COALESCE(b.number, 0) AS number
FROM tablea a
LEFT JOIN tableb b
ON a.category = b.category;
But this answer assumes that the a table would contain every category which you want to appear in your result set. For a more general solution, we might have to use a full outer join:
SELECT
COALESCE(a.category, b.category) AS category,
COALESCE(a.number, 0) + COALESCE(b.number, 0) AS number
FROM tablea a
FULL OUTER JOIN tableb b
ON a.category = b.category;
You can use union all and aggregation:
select category ,sum(number) value
from (
select category, number from tablea
union all select category, number from tableb
)
group by category
Another option is to do a full outer join: this would allow values coming from both sides of the join:
select
coalesce(ta.category, tb.category) number,
sum(coalesce(ta.number, 0) + coalesce(tb.number, 0)) value
from tablea ta
full outer join tableb tb on ta.category = tb.category
group by coalesce(ta.category , tb.category )
I should have used nvl(). This works:
select a.category, nvl(a.number, 0) + nvl(b.number, 0) as number
from a
right join b
on a.category = b.category
JOIN
SELECT *
FROM a
INNER JOIN (
SELECT b.id, Count(*) AS Count
FROM b
GROUP BY b.id ) AS b ON b.id = a.id;
LATERAL
SELECT *
FROM a,
LATERAL (
SELECT Count(*) AS Count
FROM b
WHERE a.id = b.id ) AS b;
I understand that here join will be computed once and then merge with the main request vs the request for each FROM.
It seems to me that if join will rotate a few rows to one frame then it will be more efficient but if it will be 1 to 1 then LATERAL - I think right?
If I understand you right you are asking which of the two statements is more efficient.
You can test that yourself using EXPLAIN (ANALYZE), and I guess that the answer depends on the data:
If there are few rows in a, the LATERAL join will probably be more efficient if there is an index on b(id).
If there are many rows in a, the first query will probably be more efficient, because it can use a hash or merge join.
Code:
Select a.x,
a.y,
b.p,
c.i
from table1 a left join table2 b on a.z=b.z
left join table3 on a.z=c.z;
When I am using the above code I am not getting the correct counts:
Table1 has 30 records.
After first left join I get 30 records but after 2nd left join I am getting 33 records.
I am having hard time figuring out why I am getting different counts. According to my understanding I should be getting 30 counts even after the 2nd left join.
Can anyone help me understand this difference?
I am using sql server 2012
There are multiple rows in table3 with the same z value.
You can find them by doing:
select z, count(*)
from table3
group by z
having count(*) >= 2
order by count(*) desc;
If you want at most one match, then outer apply can be useful:
Select a.x, a.y, b.p, c.i
from table1 a outer apply
(select top 1 b.*
from table2 b
where a.z = b.z
) b outer apply
(select top 1 c.*
from table3 c
where a.z = c.z
) c;
Of course, top 1 should be used with order by, but I don't know which row you want. And, this is probably a stop-gap; you should figure out why there are duplicates.
In your table table3 contain more then 1 row per 1 row in table1. Check one value which is occured more times in both tables.
You can use group by with max function to make one to one row.
I have to use the result from one inner join table and subsequently get the records that are not present in another linking table:
To check whether a value is not in a set of values, use NOT IN:
SELECT *
FROM A
WHERE some_ID NOT IN (SELECT C.some_ID
FROM B
JOIN C ON ...)
Alternatively, use a correlated subquery, which does a separate lookup for each record in the outer query:
SELECT *
FROM A
WHERE NOT EXISTS (SELECT 1
FROM B
JOIN C ON ...
WHERE C.some_ID = A.some_ID)
Alternatively, use an outer join and check which records did not match:
SELECT A.*
FROM A
LEFT JOIN (B JOIN C ON ...)
ON A.some_ID = C.some_ID
WHERE C.some_ID IS NULL
Can anyone explain what will happen in following scenario?
SELECT *
FROM A,
B
LEFT JOIN C
ON B.FIELD1=C.FIELD1
WHERE A.FIELD1='SOME VALUE'
Here table A and table B are not joined with any condition. So my doubt is what kind of join will be applied between A and B?
A cross join (cartesian product, if you prefer) will be applied between the results of A and B left join C: each row in the first set will be tied to each row in the second set.
A cross join applies, If you don't used a join condition, get irrelavent results also.
Please try it
SELECT * FROM A INNER JOIN B ON A.IDCOLUMND=B.IDCOLUMN LEFT JOIN C ON B.FIELD1=C.FIELD1