I want to select the max() value of the modified_at column in each of several tables:
select
max(a.modified_at) as a_modified_at,
max(b.modified_at) as b_modified_at,
max(c.modified_at) as c_modified_at
from a, b, c;
This works correctly as long as each of the tables has at least 1 row.
The problem is that when just one of the tables has 0 rows, null is returned for all tables:
null,null,null
What is a solution that returns the correct values for the tables that do have rows?
PostgreSQL-10
Using OUTER JOINs should do it
select
max(a.modified_at) as a_modified_at,
max(b.modified_at) as b_modified_at,
max(c.modified_at) as c_modified_at
from a outer join b outer join c;
but a possibly simpler option would be to use 3 subqueries instead:
select
(select max(modified_at) from a) as a_modified_at,
(select max(modified_at) from b) as b_modified_at,
(select max(modified_at) from c) as c_modified_at;
Related
Table A has 2500 rows
Table B has 12000 rows
Common column between these two tables is Email_ID.
Note: Email ID column may have nulls in table B.
If I join these tables using this query
Select count(*)
from A
left join B on A.Email_ID = B.Email_ID
it is returning a value of more than 2500 records.
But I want only 2500 records from Table A
Please suggest how to do this.
* will return total record count regardless of duplicate or nulls :
Select count(b.Email_ID) -- if you have a duplicate email ids then use `distinct`
from A left join
B
on A.Email_ID = B.Email_ID;
However, you can also use exists, join will return multiple rows if b table has more rows matching email id available in table a. So, count will always be increased.
select count(a.Email_ID)
from a
where exists (select 1 from b where b.Email_ID = a.Email_ID);
If you want only 2,500 hundred records, then why are you joining? That is, these return 2,500:
select count(*)
from A;
select count(distinct A.Email_id)
from A left join
B
on A.Email_ID = B.Email_ID;
If you actually want one row returned from B for each A, then use outer apply rather than left join:
select . . .
from a outer apply
(select top (1) b.*
from b
where b.email_id = a.email_id
) b;
This returns an arbitrary matching row from b. Normally, the subquery would have an order by to provide more control over the matching row. For instance, order by newid() would return a random row.
Lets say I have a query where one field can appear in either Table A or Table B but not both. So to retrieve it I use Coalesce.
Something like
Select
...
Coalesce(A.Number,B.Number) Number
...
From Table A
Left Join Table B on A.C= B.C
Now lets say I want to join another table to that Number field
should I just do
Join Table Z on Z.Z = Coalesce(A.Number,B.Number)
Or is it better to wrap my original table in a query and join on the definite result. So something like
Select * from (
Select
...
Coalesce(A.Number,B.Number) Number
...
From Table A
Left Join Table B on A.C= B.C
) T
left join Table Z on Z.Number= T.Number
Does this make a difference?
if i were joining another table to the result of the first query instead of a sub query i would place the first part in a CTE whenever possible, i believe the performance would be the same as a subquery but CTEs are more readable in my opinion.
with cte1 as
(
Select
...
Coalesce(A.Number,B.Number) Number
...
From Table A
Left Join Table B
on A.C= B.C
)
select *
from cte1 a
Join Table Z
on Z.Z = a.number
I have 2 tables, A and B.
I need all columns from A + 1 column from B in my select.
Unfortunately, B has multiples rows(all identicals) for 1 row in A
on the join condition.
I tried but I can't isolate one row in A for one row in B with left join for example while keeping my select.
How can I do this query ? Query in ORACLE SQL
Thanks in advance.
This is a good use for outer apply. The structure of the query looks like this:
select a.*, b.col
from a outer apply
(select top 1 b.col
from b
where b.? = a.?
) b;
Normally, you would only use top 1 with order by. In this case, it doesn't seem to make a difference which row you choose.
You can group by on all columns from A, and then use an aggregate (like max or min) to pick any of the identical B values:
select a.*
, b.min_col1
from TableA a
left join
(
select a_id
, min(col1) as min_col1
from TableB
group by
a_id
) b
on b.a_id = a.id
I'm trying to do
SELECT * FROM a, b
However, it doesn't return anything if one of the tables is empty. How do I make it so it returns 'a' even if the other one is empty?
Using two tables in the from clause is functionally equivalent to a cross join:
select *
from A
cross join
B
This returns a row of A for every row in B. When B is empty, the result is empty too. You can fix that by using a left join. With a left join, you can return rows even if one of the tables is empty. For example:
select *
from A
left join
B
on 1=1
As the condition 1=1 is always true, this is just like a cross join except it also works for empty tables.
SELECT * FROM a LEFT JOIN b ON a.ID = b.ID
Will return everything from a even if b is empty.
You should do a left join.
Like this
SELECT *
FROM A
LEFT JOIN B ON A.ID = B.ID
Then you receive the rows in A and the respective row in B if exists.
SELECT a.*, b.* FROM a LEFT JOIN b ON a.id = b.id
in this example id is just example name for join key
The query mentioned above display join of both tables if a contain 2 record and b contain 7 records it displays 7*2 = 14 records. In your case one of the table is empty( with 0 records), it will not display any data. If still you want to display data and tables are not having any relationship, you need to check if count of both tables greater that 0. Otherwise display records from only one table which is not empty.
I have two tables A and B where there is one-to-many relationship.
Now I want some records from A and with this existence field that shows if B has any matching records. I don't want to use the count function as B has too many records that delays SQL execution. Either I don't want to use proprietary keywords like rownum of Oracle like below, as I need as much compatibility as possible.
select A.*, (
select 1 from B where ref_column = A.ref_column and rownum = 1
) existence
...
You would use left join + count anyway, select statement in select list can be executed multiple times while join will be done only once.
Also you can consider EXISTS:
select A.*, case when exists (
select 1 from B where ref_column = A.ref_column and rownum = 1
) then 1 else 0 end
Use an EXISTS clause. If the foreign key in B is indexed, performance should not be an issue.
SELECT *
FROM a
WHERE EXISTS (SELECT 1 FROM b WHERE b.a_id = a.id)