I want to return results from a join where the birth_date of two+ records are the same, but the person_id's are not equal. I am using Oracle. So if I got 4 results where rows 1 & 2 have the same birth_date and different person_id, those rows would be returned. Where rows 3 & 4 have the same birth_date and same person_id, those rows would not be returned. I get results, but I want to filter our results where the birth_date of rows are equal, but the person_id is <>.
select t3.field1, t6.field2, t6.field3, t3.field4, t3.field5
from table1 t1
inner join table2 t2 on t1.#matching = t2.#matching
inner join table3 t3 on t3.#matching = t1.#matching
inner join table4 t4 on t4.#matching = t1.#matching
inner join table5 t5 on t5.#matching = t4.#matching
inner join table6 t6 on t6.#matching = t3.#matching
where t1.#requirement = 'xxx'
and t2.#requirement = 'xxx'
and t2.#requirement is null
and t4.#requirement = 'xxx'
and t5.#requirement = 'xxx'
and t1.#requirement ='xxx'
and t5.#requirement is null
order by t1.#field ASC;
SELECT a.birth_date, a.id, b.id
FROM some_table a, some_table b
WHERE a.birth_date = b.birth_date
AND a.id < b.id
Note the usage of < instead of the intuitive !=. This is done to prevent the same combination returning in different orders (e.g. (1,2) and (2,1)).
Have you tried to group your data by person_id.. This will put all the records with the same person_id into 1 record
The query would look something like this
SELECT a.birth_date, a.id, b.id
FROM some_table a, some_table b
WHERE a.birth_date = b.birth_date
AND a.id < b.id
GROUP BY a.id
Related
I want to left outer join and display all id records that appear in table1 even if they don't exist in the table2. Table1 can have multiple id records for a year so I need to select distinct.
Here is the selection of ID's i need from table1
select distinct a.id
from table1 a
where a.year = 2022
and a.type = 'R'
This will display 650 records
So here is my attempt to join with another table. I want to still see the all the results of the first query on table1 even if there is no record found in table 2. So the desired result should be 650 records in total.
select distinct a.id, b.value
from table1 a left join table2 b on
a.id = b.id
where b.month = 'JAN'
and a.year = 2022
and a.type = 'R';
My result gives me 550 records. So I am still missing 100 records which do not exist in table2 that need to be included in the query.
If I change the WHERE to an AND in the ON condition, I will get all YEARS displayed and all TYPES. Resulting in a massive amount of records.
select distinct a.id, b.value
from table1 a left join table2 b on
a.id = b.id
and b.month = 'JAN'
and a.year = 2022
and a.type = 'R';
What am I missing? I though left joins will display all records in one table even if they don't exist in another. I don't really understand how to do this will multiple conditions.
What am I missing? I though left joins will display all records in one table even if they don't exist in another. I don't really understand how to do this will multiple conditions.
A LEFT OUTER JOIN condition will display all records from the table on the left of the join and any matching ones on the right of the join or NULL values otherwise.
The conditions in the WHERE clause will only display records that are true.
You are putting the b.month = 'JAN' condition into the WHERE clause (and not into the JOIN condition) so it will look for only those rows where the WHERE clause it true and then it will not match any rows where b.month is NULL and you have effectively turned the join condition to an INNER JOIN and not a LEFT OUTER JOIN.
You have several choices:
Perform the filtering in the WHERE clause but do it in a sub-query before joining the tables:
SELECT a.id, b.value
FROM (
select distinct
id
from table1
where year = 2022
and type = 'R'
) a
LEFT OUTER JOIN (
select id, value
from table2
where month = 'JAN'
) b
ON (a.id = b.id)
Put the b.month = 'JAN' filter into the JOIN condiiton:
SELECT DISTINCT
a.id, b.value
FROM table1 a
LEFT OUTER JOIN table2 b
ON (a.id = b.id AND b.month = 'JAN')
WHERE year = 2022
AND type = 'R';
How about
select distinct a.id, b.value
from table1 a left join table2 b on a.id = b.id and b.month = 'JAN'
where a.year = 2022
and a.type = 'R';
I have a query where I'm doing a self join on TableA on 'Id1' and 'Id2'. I then do an inner join on TableB. The table with the self join as 2 keys (Id1,Id2). I'm trying to get the records that do not match up with the Id in Table3. Is it a condition that I need to add on the join? Thanks!
SELECT *
FROM TableA t1
JOIN TableA t2 ON t1.Id1 = t2.Id2
JOIN TableB t3 ON t1.Id1 = t3.Id
EDIT :
SELECT *
FROM UCDetails ucd1
JOIN MS et ON ucd1.UKey = TRY_CAST(et.SubKey AS bigint)
JOIN dbo.UCDetails ucd2 ON ucd1.UKey = ucd2.ETTSubkey
WHERE ucd1.ETTSubkey IS NULL
Sorry, I should of been more specific, so here is the query. What I want is to take only the record from ucd1 or ucd2 where if the ucd1 ETTSubkey IS NULL and the 'UKey' DOES NOT match the 'et.Subkey'. I can pull the records with this join but I only want to take the 'UCD' record where there isn't a match with the 'Subkey' on the et table.
If you want rows where either id does not match in tableB, then use not exists:
select a.*
from tableA a
where not exists (select 1
from tableB b
where b.id = a.id1
) or
not exists (select 1
from tableB b
where b.id = a.id2
) ;
I'm trying to get the records that do not match up with the Id in
Table3
If by match up you mean that TableB's Id is equal to either Id1 or Id2 in TableA, then you only need a LEFT join that filters out the matching rows:
SELECT a.*
FROM TableA a LEFT JOIN TableB b
ON b.Id IN (a.Id1, a.Id2)
WHERE b.Id IS NULL
Is there any alternate way to fetch the following data without using union?
select A.name,A.age,B.Address,C.phoneNo from table1 A,Table2 B,Table3 C where a.pkId = b.FkId and b.pkId = c.FkId
union
select A.name,A.age,B.Address,C.phoneNo from table4 A,Table5 B,Table3 C where a.pkId = b.FkId and b.pkId = c.FkId
I am using this in Hibernate and unfortunately hibernate doesnt support Union. I was just wondering if there is any other way to achieve it else ill have to write it in a procedure and save the data in temp table and fire a sql to read data from that temp table
There is an alternative for union, but it is not pretty:
select distinct coalesce(x1.name, x2.name) as name,
coalesce(x1.age, x2.age) as age,
coalesce(x1.Address, x2.Address) as age,
coalesce(x1.phoneNo, x2.phoneNo) as age,
from (select A.name, A.age, B.Address, C.phoneNo
from table1 A join
Table2 B
on a.pkId = b.FkId join
Table3 C
on b.pkId = c.FkId
) x1 full outer join
(select A.name, A.age, B.Address, C.phoneNo
from table4 A join
Table5 B
on a.pkId = b.FkId join
Table3 C
on b.pkId = c.FkId
) x2
on 1 = 0; -- always false
I can't imagine why you would want to express a union like this. I would highly recommend, though, that you start using proper, explicit join syntax.
is this working ?
SELECT
CASE DISTINCT_FLG WHEN 1 THEN nameA ELSE nameB END name,
CASE DISTINCT_FLG WHEN 1 THEN ageA ELSE ageB END age,
CASE DISTINCT_FLG WHEN 1 THEN AddressA ELSE AddressB END Address,
CASE DISTINCT_FLG WHEN 1 THEN phoneNoA ELSE phoneNoB END phoneNo
FROM (
SELECT
T1.name AS nameA, T1.age AS ageA, T2.Address AS AddressA, T3.phoneNo AS phoneNoA,
T4.name AS nameB, T4.age AS ageB, T5.Address AS AddressB, T3.phoneNo AS phoneNoB,
ROW_NUMBER() OVER(PARTITION BY T1.name, T1.age, T2.Address, T4.name, T4.age, T5.Address, T3.phoneNo ORDER BY NULL) AS DISTINCT_FLG
FROM
table1 T1,
table2 T2,
table4 T4,
table5 T5,
table3 T3
WHERE
T1.pkId = T2.FkId AND
T4.pkId = T5.FkId AND
(
T2.pkId = T3.FkId OR
T5.pkId = T3.FkId
)
) WHERE DISTINCT_FLG IN (1, 2)
Those two UNION parts have Table3 C in common, so we can join the rest to it. To emulate UNION records from the source table can be replicated through unconditional cross join of an auxiliary table with the required number or rows:
Select Distinct
CASE R.r WHEN 1 THEN A1.name ELSE A2.name END As name ,
CASE R.r WHEN 1 THEN A1.age ELSE A2.age END As age ,
CASE R.r WHEN 1 THEN B1.Address ELSE B2.Address END As Address,
C.phoneNo
From Table3 C, --< Start at common Table3
(Select Rownum r From USER_TABLES Where Rownum < 3) R --< Two rows to replicate Table3 C
-- Any table with more than one row will do
-- USER_TABLES should have enough rows in this particular case
Left Join Table2 B1 On R.r = 1 AND B1.pkId = C.FkId --< Left Join branch one
Left Join table1 A1 On R.r = 1 AND A1.pkId = B1.FkId
Left Join Table5 B2 On R.r = 2 AND B2.pkId = C.FkId --< Left Join branch two
Left Join table4 A2 On R.r = 2 AND A2.pkId = B2.FkId
Where (R.r = 1 AND A1.pkId Is NOT NULL) --/ Make sure we have values
OR (R.r = 2 AND A2.pkId Is NOT NULL) --\ for the branch
But really, consider a view.
I have two table a and b
table a
ID
a
b
c
table b
ID Value
a 1
b 2
default 0
So I want to join two tables on ID when exactly matching, otherwise use default value
The desired results
ID Value
a 1
b 2
c 0
Use a LEFT OUTER JOIN for that purpose like
select t1.ID, COALESCE(t2.Value, 0) as Value
from tablea t1
left join tableb t2 on t1.ID = t2.ID;
Try this:
SELECT a.ID, b.Value
FROM a
INNER JOIN b
ON a.ID = b.ID
UNION ALL
SELECT a.ID, b.Value
FROM a
CROSS JOIN b
WHERE
a.id <> b.id
This will provide you with all matching IDs, then the UNION of the CROSS JOIN query should provide the default value for non-matching IDs.
Try this:
SELECT t1.ID,
COALESCE(t2.Value, (SELECT Value FROM tableb t3 WHERE ID ='default')) AS Value
FROM tablea t1
LEFT JOIN tableb t2 on t1.ID = t2.ID;
I have two tables, linked with an outer join. The relationship between the primary and secondary table is a 1 to [0..n]. The secondary table includes a timestamp column indicating when the record was added. I only want to retrieve the most recent record of the secondary table for each row in the primary. I have to use a group by on the primary table due to other tables also part of the SELECT. There's no way to use a 'having' clause though since this secondary table is not part of the group.
How can I do this without doing multiple queries?
For performance, try to touch the table least times
Option 1, OUTER APPLY
SELECT *
FROM
table1 a
OUTER APPY
(SELECT TOP 1 TimeStamp FROM table2 b
WHERE a.somekey = b.somekey ORDER BY TimeStamp DESC) x
Option 2, Aggregate
SELECT *
FROM
table1 a
LEFT JOIN
(SELECT MAX(TimeStamp) AS maxTs, somekey FROM table2
GROUP BY somekey) x ON a.somekey = x.somekey
Note: each table is mentioned once, no correlated subqueries
Something like:
SELECT a.id, b.*
FROM table1 a
INNER JOIN table2 b ON b.parentid = a.id
WHERE b.timestamp = (SELECT MAX(timestamp) FROM table2 c WHERE c.parentid = a.id)
Use LEFT JOIN instead of INNER JOIN if you want to show rows for IDs in table1 without any matches in table2.
select *
from table1 left outer join table2 a on
table1.id = a.table1_id
where
not exists (select 1 from table2 b where a.table1_id = b.table1_id and b.timestamp > a.timestamp)
The quickest way I know of is this:
SELECT
A.*,
B.SomeField
FROM
Table1 A
INNER JOIN (
SELECT
B1.A_ID,
B1.SomeField
FROM
Table2 B1
LEFT JOIN Table2 B2 ON (B1.A_ID=B2.A_ID) AND (B1.TimeStmp < B2.TimeStmp)
WHERE
B2.A_ID IS NULL
) B ON B.A_ID = A.ID