UNION and NOT In Together - sql-server

SELECT name FROM table1
WHERE name NOT IN (
SELECT name, school FROM table2
UNION
SELECT name, school FROM table3
)
This syntax keeps flagging error near syntax 'Union'. Any suggestion on how to fix this please?

In the subquery, only select the name column that's used as a filter. Unless you need combination of the name and school columns, in which case they'll need to be concatenated. The space in the name of table3 will need to be removed, unless this is the actual name of the table. If it is, it will be to be enclosed in brackets, i.e. [table 3].
SELECT name FROM table1
WHERE name NOT IN (
SELECT name FROM table2
UNION
SELECT name FROM table3
)

This is functionally the same and may be faster in some cases
SELECT name
FROM table1 as t1
left join table2 as t2 on t1.name = t2.name
left join table3 as t3 on t1.name = t3.name
where coalesce(t2.name,t3.name,'new') = 'new'
you can also use a where clause like this:
where t2.name is null and t3.name is null

Related

How to INNER JOIN multiple values

SELECT t1.*, t2.name as song_name
FROM table1 as t1
INNER JOIN table2 as t2
ON t1.song_name_id = t2.id
WHERE t1.id = '..'
I get following error when t2.id column has two id's like this 6,12. Obviously, works, when record t2.id (nvarchar) is only one. How can I make it work with two/multiple?
Error:
Conversion failed when converting the nvarchar value '6,12' to data type int.
The error is possibly because table1.song_name_id and table2.id have different data types. Please ensure they are of same type or use convert function.
Don't Store CSV data in your table however a temporary solution is given below.
SELECT t1.*, t2.name as song_name
FROM table1 as t1
INNER JOIN table2 as t2
ON (t1.song_name_id = left(t2.id,1))
or(t1.song_name_id = right(t2.id,1))
WHERE t1.id = '..'
Different Approach should be handled if the table2 id column contains more than 2 values separated by commas.
As Bishakh Ghosh mentioned, you really should be joining on fields with same types, and also as Coder1991 said, you really shouldn't stored comma separated values in a single field.
Given that the field is in the state that it is, you can use pattern matching to find whether or not t2.id contains the value in t1.song_name_id.
In the below example, the additional commas will allow for "6,12" to become ",6,12," and song_name_id in the like statement will become "%,6,%" which will then find a match.
SELECT
t1.*,
t2.name as song_name
FROM
table1 as t1
INNER JOIN table2 as t2 ON
',' + t2.id + ',' LIKE '%,' + CONVERT(VARCHAR(20),t1.song_name_id) + ',%'
WHERE
t1.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

SQL - Using a join on a column with multiple values in cells

I have two tables I am trying to join. One table has a column with IDs in it, and I am trying to do a left join to a different table that has the same IDs in it, although the second table could contain more than one ID per cell. For example, if my first table has an ID value of 123, and the second table has an ID value of 123;724;823, is there any way to get it to join the two rows?
You tried in query designer? Is very easy to make joins there.
SELECT column_names
FROM table-name1 LEFT JOIN table-name2
ON ID_column-name1 = ID_Column-name2
WHERE condition X,Y,Z
Hope will help you.
select *
from
(
select '123' as id
union select '124'
) as t1
left join
(
select '123;001;002' as id
union select '001;123;002'
union select '001;002;123'
) as t2 on
t2.id = t1.id
or t2.id like t1.id + ';%'
or t2.id like '%;' + t1.id + ';%'
or t2.id like '%;' + t1.id
Using the multiple like operators is probably the fastest way, but if you have a string splitter function like this one DelimitedSplit8K, you can split the values out into a table and join to it.
SELECT *
FROM table1 t1
LEFT JOIN (
SELECT *
FROM table2 t2
OUTER APPLY (
SELECT *
FROM dbo.[DelimitedSplit8K] (t2.id,';') -- splits the values in multi id column
) t
) t ON t.Item = t1.id -- t.Item is the value generated from the DelimitedSplit8K TVF

T-SQL Join on columns OR fixed value

I'm trying to figure out some basic rules in T-SQL.
What I'm trying to achieve here, is to get only the records from Table1 which has a match in Table2 - AND - all records from Table1 where the 'Valid' column has a value of 1 (=true).
Previously I've done this with two selects and a UNION like this:
SELECT T1.*
FROM Table1 T1
INNER JOIN Table2 T2 ON T1.ID = T2.ID
UNION
SELECT T1.*
FROM Table1 T1
WHERE T1.Valid = 1
But isn't there any other way than using multiple selects and UNION to achieve this?
While fiddling, I did the following code bit, which however only works if there's exactly one match in Table2 (otherwise it'll multiply the records by the number of matches in T2).
SELECT T1.*
FROM Table1 T1
INNER JOIN Table2 T2 ON T1.ID = T2.ID
OR T1.Valid = 1
What would be the best way to achieve my goal in terms of performance?
Also please don't hold back on the comments, possible flaws, or explanations of how and why another solution might be better.
assuming that T1.ID and T2.ID is unique or a primary key:
If there are duplicates you may have to write SELECT DISTINCT T1.*. The UNION operator in the orinal selects only distinct values.
this one should do:
SELECT T1.*
FROM Table1 T1
WHERE T1.ID IN ( SELECT T2.ID FROM Table2 T2 WHERE T2.ID IS NOT NULL)
OR T1.Valid = 1
or
SELECT T1.*
FROM Table1 T1
LEFT JOIN Table2 T2 ON T1.ID = T2.ID
WHERE T2.ID IS NOT NULL OR T1.Valid = 1
but i think, the execution plan will be the same at the end.

Delete from SQL table where ID is found from conditions applied to another table

First of all, I don't know if the title is right but let me show you what I want and I will correct it as suggested.
So, I have 2 tables:
table1
ID, subid, name
table2
ID
What I want is to delete any element from table2 that has ID equal to subid in table1, where table1.name is equal to a specified value.
If I have these elements in table1
ID subid name
1 ... 1 ...... name1
2 ... 3 ...... name2
3 ... 2 ...... name1
4 ... 1 ...... name2
and these rows in table2
ID
1
2
3
4
I would like to remove those elements in table2 with ID = subid, when name = name1, which means elements 1 and 2.
Something like:
DELETE FROM table2
WHERE ID = (SELECT subid
FROM table1
WHERE NAME = "name1")
Is this possible?
You were very close.
You just need = ANY rather than = as the subquery can return more than one row SQL Fiddle.
DELETE
FROM table2
WHERE ID = ANY (SELECT t1.subid
FROM table1 t1
WHERE t1.name = 'name1')
Though this is more commonly expressed using IN
DELETE
FROM table2
WHERE ID IN (SELECT t1.subid
FROM table1 t1
WHERE t1.name = 'name1')
A couple of other changes I made to your posted query...
I always ensure that column references in subqueries use two part names to avoid unfortunate surprises.
You should use single quotes to delimit string literals so it works under default QUOTED_IDENTIFIER settings and is not interpreted as referencing a column called name1.
You can delete using joins as well, so yup very possible.
You can identify the (to be) deleted records first with:
select t2.*
from table2 t2
inner join table1 t1 on t2.id = t1.subId
and t1.name = 'whatever'
then perform the delete as such:
delete t2
from table2 t2
inner join table1 t1 on t2.id = t1.subId
and t1.name = 'whatever'
#eckes see my fiddle with the syntax that I'm using to see it works: http://sqlfiddle.com/#!6/260a5

Resources