NOT IN condition in SQL - sql

Can anyone tell me the exact syntax for NOT IN condition in SQL on two columns.
This is my query written in VBA.
strNewSql = "SELECT distinct(tblRevRelLog_Detail.PartNumber), tblRevRelLog_Detail.ChangeLevel, tblRevRelLog_Detail.ID FROM tblRevRelLog_Detail LEFT JOIN tblEventLog ON tblRevRelLog_Detail.PartNumber = tblEventLog.PartNumber"
strNewSql = strNewSql & " WHERE (tblEventLog.PartNumber) Not In(SELECT tblEventLog.PartNumber FROM tblEventLog WHERE tblEventLog.EventTypeSelected = 'pn REMOVED From Wrapper') AND tblEventLog.TrackingNumber = """ & tempTrackingNumber & """ AND tblEventLog.TrackingNumber = tblRevRelLog_Detail.RevRelTrackingNumber;"
I want to change this sub query like, it should apply on the combination of two columns as follows:
strNewSql = "SELECT tblRevRelLog_Detail.PartNumber, tblRevRelLog_Detail.ChangeLevel, tblRevRelLog_Detail.ID FROM tblRevRelLog_Detail LEFT JOIN tblEventLog ON tblRevRelLog_Detail.PartNumber = tblEventLog.PartNumber"
strNewSql = strNewSql & " WHERE (((tblEventLog.PartNumber, tblEventLog.PartNumberChgLvl) Not In(SELECT tblEventLog.PartNumber,tblEventLog.PartNumberChgLvl FROM tblEventLog WHERE tblEventLog.EventTypeSelected = 'pn REMOVED From Wrapper') AND tblEventLog.TrackingNumber = """ & tempTrackingNumber & """ AND tblEventLog.TrackingNumber = tblRevRelLog_Detail.RevRelTrackingNumber);"
But this is not working.....

You can't use IN with more than one column but you can usually achieve the same effect using EXISTS:
SELECT *
FROM tbl1
WHERE NOT EXISTS
(
SELECT *
FROM tbl2
WHERE tbl2.col1 = tbl1.col1
AND tbl2.col2 = tbl1.col2
)

General syntax:
where col not in (items)
Items can be
a list of items -- (4,5,3,5,2) or ('243','3','cdds') or any other datatype.
Or a select statement (select hatefulthings from table)
Addition 6 years later
All major platforms support tuples with NOT IN, for example
SELECT *
FROM empoyee
WHERE (empID, #date) NOT IN
(SELECT empID, vacationDay
FROM empVacation
)
In this example we select everything from the employee table where the tuple of employee id and date are not in a table containing vacation days.

Your question is a bit unclear. Is this what you need?
SELECT *
FROM
MY_TABLE MT
WHERE 'Smith' NOT IN (MT.FIRST_NAME)
AND 'Smith' NOT IN (MT.LAST_NAME)
This will show you all records where the search phrase ("Smith") is in neither the first_name nor the last_name column.

Perhaps you meant
SELECT *
FROM MY_TABLE
WHERE (FIRST_NAME, LAST_NAME) NOT IN (SELECT FIRST_NAME, LAST_NAME
FROM SOME_OTHER_TABLE)
This is allowed under Oracle - not sure about SQL Server.
Share and enjoy.

Select * from some_table
where (((Some_Value) Not IN (Select Column1 & Column2 from Some_Other_Table)));
I saw where you indicated this was for Access

It is not clear what you are asking, but I gather that you would like to have a NOT IN condition based on two columns instead of just one.
As an example, lets say you have a column called F_Name and another called L_Name (both variable in size), and that you want to exclude specific combination of those names from another table that has them already combined as NAME. In that case, you could do this:
select F_name
, L_name
, col1
, coln
from mytable1
where F_name -- First name (variable length)
|| ' ' -- appended to a blank space
|| L_name -- appended to the last name (v)
not in -- is not one of these names
( select name
from mytable2
where ...
)
The main issue with this query is that you must get the formatting just right so that they can match up exactly.
If you are dealing with a combination of fields with different types, like numeric and timestamps, then use any of the conversion commands (DECIMAL, INTEGER, CHAR, SUBSTR ...) at your disposal to convert to text equal and then match it up accordingly.

Related

Join data inside a column instead of combining columns

I have this query that joins all the columns I want:
select * from Customer c
inner join Tier t on c.TierId = t.Id
However I don't want all the columns combined. I would like to have a Tier column and then have the full tier record in this column (as I am mapping to json and it has to be in this format).
How do I create subgroup like that?
I tried:
select *, Tier = (select * from Tier t where t.Id = c.TierId ) from Customer c
inner join Tier t on c.TierId = t.Id
can someone point in right direction please.
Edit:
So I want something like this:
- CustomerID
- CustomerName
- CreatedDate
- Tier <-- all tier columns as a subgroup like when you group by
- TierId
- TierName
Are you looking to select just one column from tier? Be explicit about the columns you want:
select t.tier, c.*
from Customer c inner join
Tier t
on c.TierId = t.Id;
It seems like what you need is sql CONCAT Function.
The query would look something like that:
SELECT CONCAT("[", column1, ", ", column2, "]") AS tier FROM Tier
SQLite doesn't support CONCAT so you have to use the || operator like this:
SELECT ("[" || column1 || ", " || column2 || "]") AS tier FROM Tier
The brackets will mark it as an array in JSON, you can remove them if you want.
You can also add the columnname to the result by just adding them as a string to make it more
NOTE: You won't be able to access the values like an Array because this simply merges the values to a String

In SELECT, correlated subquery in select to transform rowID into rowname

How to combine these 2 sets of code?
Tables: geregistreerd g, instrument i and indeling id.
I want to display g.voornaammuzikant, g.achternaammuzikant, i.naaminstrument, id.familie.
Table g is linked with table i with instrumentid
Table i is linked with table id with indelingid
--oefening 1:
SELECT TRIM(' ' FROM g.voornaammuzikant), TRIM(' ' FROM g.achternaammuzikant),
(SELECT i.naaminstrument
from instrument i
where i.instrumentid = g.instrumentid) as "naam instrument"
from geregistreerd g
order by g.voornaammuzikant;
--oefening 2:
SELECT i.naaminstrument,
(SELECT id.familie
from indeling id
where i.indelingid = id.indelingid) as "familie",
(SELECT id.onderfamilie
from indeling id
where i.indelingid = id.indelingid) as "onderfamilie"
from instrument i
order by i.naaminstrument;
COMBINED
SELECT TRIM(' ' FROM g.voornaammuzikant),
TRIM(' ' FROM g.achternaammuzikant),
(SELECT i.naaminstrument
(SELECT id.familie
from indeling id
where i.indelingid = id.indelingid) as "familie"
from instrument i
where i.instrumentid = g.instrumentid) as "naam instrument"
from geregistreerd g
order by g.voornaammuzikant;
Why would you want to do things in a complicated way, if they can be simplified? What's wrong with a simple join? Something like this:
select g.voornaammuzikant,
g.achternaammuzikant,
i.naaminstrument,
id.familie
from geregistreerd g join instrument i on i.instrumentid = g.instrumentid
join indeling id on id.indelingid = i.indelingid
order by g.voornaammuzikant;
By the way, those TRIMs you posted don't look good. SELECT TRIM(' ' FROM g.voornaammuzikant) is certainly wrong; I don't know what you meant to say with that. Perhaps removing superfluous spaces from those values? If they exist, is - by any chance - that column's datatype CHAR? If so, consider switching to VARCHAR2 because the former pads values with spaces up to the whole length of that column.

SQL Query Joining Update and Select in a single statement

Need a SQL query to perform UPDATE and SELECT in a single statement.
I have two tables.
First I need to filter the second table
After filtering the second table, I need to update first table from the resultant filtered second table.
update statement followed by Select statement
You haven't told us what your database is, but this will work for SQL Server.
update FirstTable
set f.FirstName = case when f.FirstName = s.MiddleName then s.FN else f.FirstName end,
f.LastName = case when f.LastName = s.MiddleName then s.FN else f.LastName end
from FirstTable f
inner join SecondTable s on f.FirstName = s.MiddleName or f.LastName = s.MiddleName
where s.FN <> 'aaa' -- Missed first time
I don't think it will work exactly as laid out for other RDBMs'.
EDIT: Added the where to the SQL, and the explanation that follows:
The query is of the form:
update table1
set col1 = x.colN
from table1 t
inner join table2 x on some condition
This is in two parts the update + set lines, and the from query which is a complete select statement without the actual select column list. Think of the second as being prefixed by 'select *'.
The second part (the guts of a select statement) must use the same table as the update part - FirstTable in your problem and table1 in the skeleton above. Since it selects rows from the same table as the update it knows which rows you want to update, and makes the columns in the select part available to the update part. In the skeleton, I can then set col1 from table1 to colN from table2.
Your problem is a bit more complicated as I don't necessarily want to change FirstName or LastName. To take FirstName, I want to change FirstName to FN when FirstName = MiddleName. To do this I use a case as part of the set:
set f.FirstName = case when f.FirstName = s.MiddleName then s.FN else f.FirstName end
This says the when FirstName = MiddleName then set FirstName o FN, else set it to FirstName (in other words don't change it).
Repeat for LastName.
Hope that helps.

Only one expression can be specified in the select list when the subquery is not introduced with EXISTS

(SELECT
Dbo.DecryptString(LastName) + '', '' +
Dbo.DecryptString(FirstName) as PatientName
FROM Persons.Informations
WHERE PersonId = (SELECT PersonId
FROM Patients.Informations
WHERE PatientId = TST.PatientId))
From Transactions.SessionTransaction TST ON TST.PaymentId = TP.PaymentId
Can you tell me what is wrong with this query?
Why does it through the error:
"Only one expression can be specified in the select list when the
subquery is not introduced with EXISTS."
You have to use the IN predicate instead of =, in case you have to compare multiple values returned by the WHERE clause, so in your query, instead of
WHERE PersonId = (SELECT PersonId
FROM Patients.Informations
WHERE PatientId = TST.PatientId)
Try this instead:
...
WHERE PersonId IN (SELECT PersonId
FROM Patients.Informations
WHERE PatientId = TST.PatientId)
...
However, you can JOIN the tables directly, instead of this predicate IN, like so:
SELECT
...
FROM Persons.Informations i
INNER JOIN Transactions.SessionTransaction TST ON i.PersonId = TST.PersonId
INNER JOIN ... TP ON TST.PaymentId = TP.PaymentId
If you're trying to combine the last and first names together, separated by a comma, you have too many quote marks:
(SELECT
Dbo.DecryptString(LastName) + ', ' +
Dbo.DecryptString(FirstName) as PatientName
FROM Persons.Informations
WHERE PersonId = (SELECT PersonId
FROM Patients.Informations
WHERE PatientId = TST.PatientId))
From Transactions.SessionTransaction TST ON TST.PaymentId = TP.PaymentId
Your original query is trying to return two columns - the last name with an empty string appended to it (effectively a no-op), and the first name with an empty string prepended to it (again, effectively a no-op).

Combine two different select statements, one distinct the other not

I have two selects which are required to filter data. They are not complicated:
"SELECT * FROM StevesTable t WHERE "
"t.data1 = '%s' AND "
"t.data2 = to_date('%s','DD/MM/YYYY');",
strdata1,
dtDate.Format();
and
SELECT distinct data1 FROM anothertable ftt
join table1 tab on tab.somedata = ftt.somedata
where tab.somedata = 0
and tab.someotherdata = 1
I would like to combine these two as I need to filter the returned dataset from the first select statement by the returned field in the second (ie if a record returned in the first set does not have a data1 value which is contained in the second returned set it is invalid).
I tried to union and intersect the selects but you need the same number of columns returned and that cannot happen as these are completely different tables. When I tried to simply merge them together I found it difficult as the second select statement is a distinct select whereas the first is not.
I was wondering whether I had missed a trick somewhere for combining these sorts of selects?
What you need is a SQL sub-query:
SELECT * FROM StevesTable t
WHERE t.data1 = '%s'
AND t.data2 = to_date('%s','DD/MM/YYYY')
AND t.data1 in (select distinct data1 FROM anothertable ftt
join table1 tab on tab.somedata = ftt.somedata
where tab.somedata = 0
and tab.someotherdata = 1)
There, you check that all records in the first select have a data1 value in the second set.
You can do this using an EXISTS condition:
SELECT * FROM StevesTable t
WHERE t.data1 = '%s' AND
t.data2 = to_date('%s','DD/MM/YYYY') AND
EXISTS (select null
from anothertable ftt
join table1 tab on tab.somedata = ftt.somedata
where tab.somedata = 0 and
tab.someotherdata = 1 and
ftt.data1 = t.data1)