SQL join greater than / less then - sql

I have 2 tables
I
So i need to get a table in which rows will be excluded for which the date for each "id" is more than in the second table "datestop"
I tried inner join with double condition:
id = id and Date < DateStop, but in this way also excluded rows which not contained in table 2 (id1)
For imagine, thats what i want to get:

I would use NOT EXISTS which is very efficient:
select t1.*
from table1 t1
where not exists (
select 1 from table2 t2
where t2.id = t1.id and t2.datestop <= t1.date
)
It's not clear if you need the value of Status must be 'Stopped' for your requirement.
So maybe you need to change the WHERE clause of the subquery to:
where t2.id = t1.id and t2.datestop <= t1.date and t2.status = 'Stopped'

Consider:
select a.*
from tablea a
left join tableb b on b.id = a.id
where b.id is null or b.datestop > a.date
This phrases as: get all records in tablea for which either there is no record with the same id in tableb, or whose date is less than the datestop of the corresponding record in tableb.

This is a situation where all can be helpful:
select a.*
from a
where a.date < all (select b.datestop
from b
where b.id = a.id and b.status = 'Stopped'
);

Related

SQL Self Join and take a record by a condition on a third join

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

How to get first row value from third table while joining three tables

I'm new to mssql .Here am trying to get values from database by joining three tables .
Table 1:
Table 2 :
Here the image there is a possibility for a single user can have multiple image id form this I need to take any one of the image.
Table 3 :
Here am joining the Table 1 and Table 2 by using H_ID
and Table 2 and Table 3 by using IMG_ID.
What I want to do is Need to get all the colum values from Table 1 and Table 2 But the first URL from the Table 3.
In this case an employee has multiple images in the Table I need to take the 1 URL.
Result should be like this :
Query :
SELECT T1.H_ID AS 'ID',
T1.NAME,
T1.ROLE,
T2.SALARY,
T3.IMAGE
FROM TABLE1 T1
JOIN TABLE2 T2
ON T1.H_ID T2.H_ID
JOIN TABLE3 T3
ON T3.IMG_ID = T2.IMG_ID
WHERE T1.STATUS = 'ACTIVE'
Now this query returns 3 rows for the id H_ID = 1001 but It should be a single row.
Can anyone help me to fix this .
use row_number()
with cte as
(SELECT T1.H_ID AS 'ID',T1.NAME,T1.ROLE,T2.SALARY,T3.IMAGE
,row_number() over(partition by T2.img_id order by T3.id) rn
FROM TABLE1 T1
JOIN TABLE2 T2
ON T1.H_ID T2.H_ID
JOIN TABLE3 T3
ON T3.IMG_ID = T2.IMG_ID WHERE T1.STATUS = 'ACTIVE'
) select * from cte where rn=1
After you comments it seems you need subquery
select T1.*,T2.sal,a.url
FROM TABLE1 T1
JOIN TABLE2 T2
ON T1.H_ID T2.H_ID
left join ( select min(id),img_id,url from table3 group by img_id,url) a
on T2.IMG_ID= a.img_id
WHERE T1.STATUS = 'ACTIVE'
I think, You can simply use OUTER APPLY and TOP 1 for that
SELECT T1.H_ID AS 'ID',
T1.NAME,
T1.ROLE,
T2.SALARY,
T3.IMAGE
FROM TABLE1 T1
JOIN TABLE2 T2 ON T1.H_ID T2.H_ID
OUTER APPLY(SELECT TOP 1 T3.IMAGE
FROM TABLE3 T3 WHERE T3.IMG_ID = T2.IMG_ID
--ORDER BY <column_name> --to take top 1 value in specific order
) T3
WHERE T1.STATUS = 'ACTIVE'

using where clause with Union

I have two tables, t1 and t2, with identical columns(id, desc) and data. But one of the columns, desc, might have different data for the same primary key, id.
I want to select all those rows from these two tables such that t1.desc != t2.desc
select a.id, b.desc
FROM (SELECT * FROM t1 AS a
UNION ALL
SELECT * FROM t2 AS b)
WHERE a.desc != b.desc
For example, if t1 has (1,'aaa') and (2,'bbb') and t2 has(1,'aaa') and (2,'bbb1') then the new table should have (2,'bbb') and (2,'bbb1')
However, this does not seem to work. Please let me know where I am going wrong and what is the right way to do it right.
Union is not going to compare the data.You need Join here
SELECT *
FROM t1 AS a
inner join t2 AS b
on a.id =b.id
and a.desc != b.desc
UNION ALL dumps all rows of the second part of the query after the rows produced by the first part of the query. You cannot compare a's fields to b's, because they belong to different rows.
What you are probably trying to do is locating records of t1 with ids matching these of t2, but different description. This can be achieved by a JOIN:
SELECT a.id, b.desc
FROM t1 AS a
JOIN t2 AS b ON a.id = b.id
WHERE a.desc != b.desc
This way records of t1 with IDs matching records of t2 would end up on the same row of joined data, allowing you to do the comparison of descriptions for inequality.
I want both the rows to be selected is the descriptions are not equal
You can use UNION ALL between two sets of rows obtained through join, with tables switching places, like this:
SELECT a.id, b.desc -- t1 is a, t2 is b
FROM t1 AS a
JOIN t2 AS b ON a.id = b.id
WHERE a.desc != b.desc
UNION ALL
SELECT a.id, b.desc -- t1 is b, t2 is a
FROM t2 AS a
JOIN t1 AS b ON a.id = b.id
WHERE a.desc != b.desc
The UNION operator is used to combine the result-set of two or more SELECT statements.
Notice that each SELECT statement within the UNION must have the same number of columns. The columns must also have similar data types.
So, if it has same number of columns and same datatype, then use Union otherwise join only Can be used.
SELECT *
FROM t1 AS a
inner join t2 AS b
on a.id =b.id
and a.desc != b.desc

Join when exact match other other wise join with default value

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;

How Can i select a field and check it with itself?

i want to say
select col1,col2,col3
from table1
inner join table2 on table1.col1=table2.col1
and ..... ( ? )
? : i want just 1 record or first record from table1 joined with first record from table2. but the command cause all record joined that can be join. for example if 2 records are in the table1 that col1=1432 and just 1 record in table2 exists that col1=1432 command joined all. but i want to join just first from table1 with first from table2
i want to display all record that are more than 1 record to be join.
i want just 1 record or first record from table1 joined with first
record from table2
Here you go:
select top 1 col1,col2,col3
from table1
inner join table2 on table1.col1=table2.col1
and .....
Try this query -
SELECT *
FROM dbo.table1 t1
JOIN (
SELECT TOP 1 *
FROM dbo.table2
) t2 ON t1.col1 = t2.col1
If you're on SQL Server 2005 or above, you can try a ranking function to grab only the first record of each group:
select *
from (
select a.col1
, a.col2
, a.col3
-- Use the order by to determine which rows will be ranked first for each group
, row_number() over (partition by a.col1 order by a.col2) as rownum
from table1 as a
join table2 as b on a.col1 = b.col1
) as q
where rownum = 1 -- Only get the first row of each group
i want to display all record that are more than 1 record to be join.
You can add this to your where clause:
and exists (
select col1
from table1
where col1 = q.col1
group by col1
having count(*) > 1
)
To offer another solution that doesn't use a ranking function, I think we would need to know more about your tables, especially unique keys and how you define the first record of each group.