sql query to get record by multiple values - sql-server

I need a sql query that can get records from multiple table. Please check the scenario below -
There are 2 tables - Table1 and Table2
Below is the query.
Table1 :
PID PName
1 A
2 B
Table2 : (There is a foreign key relationship b/w Table1 and Table2 by 'PID')
PPID PID RID
101 1 222
102 1 333
103 2 001
104 2 002
And I want query that can get records from Table1 (I need PName) and Table2 like that-
SELECT t1.PName FROM Table1
INNER JOIN Table2 on t1.PID = t2.PID
where t2.PID = '222' and t2.PID = '333'
or
SELECT t1.PName FROM Table1
INNER JOIN Table2 on t1.PID = t2.PID
INNER JOIN dbo.StringSplit('222,333', ',') AS t on t2.PID = t.item
But in both cases I am not getting the correct resutl.
I want records where PID should exists for both RID's like - 222 and 333
The output should be like this -
PName
A
Can anyone help me out on this ?

This is a common question. It is easy to do with grouping:
select min(PName) as PName
from Table1 t1 inner join Table2 t2 on t2.PID = t1.PID
where t2.RID in ('222', '333')
group by t1.PID
having count(*) = 2
Your sample data is limited and it's not clear what is the significance of the special values "111" and "222". Depending on the actual relationship you may really want a variation like count(*) >= 2 or count(distinct t2.RID) = 2 instead.
Btw, a few of the other answer are using a left join and then filtering on the inner table afterward in the where clause. In general that would be incorrect but in your case it wouldn't change your results because the outer join isn't relevant in the first place. Whichever solution you select, don't use an outer join here.

Your first query will always return 0 results as t2.PID cannot equal both 222 and 333.
If I understand your question correctly, you want to include results where PID is 222 OR 333. E.g.
SELECT t1.PName, t2.RID FROM Table1
INNER JOIN Table2 on t1.PID = t2.PID
where t2.PID = '222' OR t2.PID = '333'

You need to use LEFT JOIN:
SELECT t1.PName, t2.RID FROM Table1 t1
LEFT JOIN table2 t2
ON t1.PID = t2.PID
WHERE t2.RID = '222' OR t2.RID = '333'

You could use distinct
SELECT DISTINCT PNAME FROM dbo.Table1
INNER JOIN dbo.Table2 ON Table11.PID = TABle22.PID
WHERE rid IN ('222','333')

Related

Different Filters for Different Columns

I am relatively new to SQL and I have the following question. I have the following code:
Select * from table1
LEFT JOIN table2 ON table1.name = table2.name and table1.id = table2.id
LEFT JOIN (SELECT id FROM table2 GROUP BY id) newtable ON table1.id = newtable.id
As both left joins uses data from the same table, is it possible to combine the two joins into one? How would the filters work in this case?
If your goal just to join table2 based on distinct values, then you can use WHERE and GROUP BY:
Select
*
from table1 t1
LEFT JOIN table2 t2
ON t1.name = t2.name and t1.id = t2.id
WHERE t1 id in (SELECT s2.id FROM table2 s2 GROUP BY s2.id)

replace nested where condition with join

I have a SQL query that looks like this
Select a.*
From table1 a
where a.ColumnName in
(Select MAX(b.ColumnName)
from table2 b
where b.ColumnName2 in
(
Select MAX(c.columnName)
from table3 c
Group by c.ColumnName2
)
Group by b.ColumnName2
)
I am trying to write this in a join statement. I am positive inner join is what I need to get the right information. If someone could translate this to a join statement, I would be really glad.
Thank you.
EDIT 1:
I tried the typical Join statement that a rookie would.
Select a.*
from table1 a
inner join table2 b
on a.columnname = (Select max(b.columnName) from table2)
inner join table3 c
on b.columnName = (select max(c.columnName) from table3)
Obviously, that didn't work because I get 100,000+ results when I should be getting 800. I tried using an alias for table2 and table3 INSIDE the subselect statements and selecting the columnname using THAT alias like this:
Select max(bPart.columnName from table2 bPart)
Select max(cPart.columnName from table3 cPart)
Still the same result.
PERHAPS....
Though I'm not sure why a join is needed. Performance wise exists would likely be fastest, and since you're not returning values from table2 or 3 it seems like it would be the best approach.
SELECT a.*
FROM table1 a
INNER JOIN (SELECT MAX(ColumnName) MColumnName, columnname2
FROM table2
GROUP BY columnName2) B
ON A.columnName = B.mColumnName
INNER JOIN (SELECT MAX(columnName) mColumnName
FROM table3
GROUP BY ColumnName2) C
ON B.columname2 = C.MColumnName

Using where condition in sql query

I have an sql query like this
Select col1, (select abc from table2 where def=1) as col2
From Table1 inner join table3 on Table1.id = table3.id
Where col2 = 4
The problem is that the where condition doesn't work. I get an error saying
Invalid column name 'col2'
Kindly help me fix this sql query.
Thanks in advance
You can define it in a CROSS APPLY and then reference in the SELECT and WHERE
SELECT col1,
col2
FROM Table1
INNER JOIN table3
ON Table1.id = table3.id
CROSS APPLY (SELECT abc
FROM table2
WHERE def = 1) C(col2)
WHERE col2 = 4
Using a CTE (Common Table Expression):
WITH SubQuery AS (Col2) {
SELECT
ABC
FROM
table2
WHERE
def = 1
}
SELECT
T.Col1,
S.Col2
FROM
SubQuery S,
Table1 T
INNER JOIN table3 t3
ON T.id = t3.id
WHERE
S.Col2 = 4
Although I must say I agree with the first comment - this makes no sense since your subquery is not correlated (joined) to the rest of your query...

Opposite Of An Inner Join Query

Table 1 2 columns: ID, Name
Table 2 2 columns: ID, Name
What is a query to show names from Table 1 that are not in table 2? So filtering out all the names in table 1 that are in table 2 gives the result query. Filtering is on ID not name.
Select * from table1
left join table2 on table1.id = table2.id
where table2.id is null
This should perform better than the left join...is null version. See here and here for comparisons.
select t1.id, t1.name
from table1 t1
where not exists(select null from table2 t2 where t2.id = t1.id)
Use this query
select
t1.*
from table1 t1
left outer join table2 t2
on t1.id=t2.id
where t2.id is null
this works by joining everything in t1 to whatever exists in t2. the where clause filters out all of the records that don't exist in t2.
SELECT Table1.ID, Table1.Name, Table2.ID
FROM Table1 LEFT OUTER JOIN Table2 ON Table1.ID = Table2.ID
WHERE Table2.ID IS NULL
I think that should do it.
Try like this:
select t1.*
from table1 as t1
where t1.id not in
(select distinct t2.id from table2 as t2);

Limited T-SQL Join

This should be simple enough, but somehow my brain stopped working.
I have two related tables:
Table 1:
ID (PK), Value1
Table 2:
BatchID, Table1ID (FK to Table 1 ID), Value2
Example data:
Table 1:
ID Value1
1 A
2 B
Table 2:
BatchID Table1ID Value2
1 1 100
2 1 101
3 1 102
1 2 200
2 2 201
Now, for each record in Table 1, I'd like to do a matching record on Table 2, but only the most recent one (batch ID is sequential). Result for the above example would be:
Table1.ID Table1.Value1 Table2.Value2
1 A 102
2 B 201
The problem is simple, how to limit join result with Table2. There were similar questions on SO, but can't find anything like mine. Here's one on MySQL that looks similar:
LIMITing an SQL JOIN
I'm open to any approach, although speed is still the main priority since it will be a big dataset.
WITH Latest AS (
SELECT Table1ID
,MAX(BatchID) AS BatchID
FROM Table2
GROUP BY Table1ID
)
SELECT *
FROM Table1
INNER JOIN Latest
ON Latest.Table1ID = Table1.ID
INNER JOIN Table2
ON Table2.BatchID = Latest.BatchID
SELECT id, value1, value2
FROM (
SELECT t1.id, t2.value1, t2.value2, ROW_NUMBER() OVER (PARTITION BY t1.id ORDER BY t2.BatchID DESC) AS rn
FROM table1 t1
JOIN table2 t2
ON t2.table1id = t1.id
) q
WHERE rn = 1
Try
select t1.*,t2.Value2
from(
select Table1ID,max(Value2) as Value2
from [Table 2]
group by Table1ID) t2
join [Table 1] t1 on t2.Table1ID = t1.id
Either GROUP BY or WHERE clause that filters on the most recent:
SELECT * FROM Table1 a
INNER JOIN Table2 b ON (a.id = b.Table1ID)
WHERE NOT EXISTS(
SELECT 1 FROM Table2 c WHERE c.Table1ID = a.id AND c.BatchID > b. BatchID
)

Resources