WHERE IN sql query - sql

I need to find which items in WHERE IN clause do not exist in the database. in below example cc33 does not exist and I need the query to give back cc33.
how would I do that ?
SELECT id FROM tblList WHERE field1 IN ('aa11','bb22','cc33')

You need to put the values into a table rather than a list:
with list as (
select 'aa11' as val union all
select 'bb22' union all
select 'cc33'
)
select l.val
from list l left outer join
tbllist t
on l.val = t.field1
where t.field1 is null

For SQl-Server versions of 2008+, you can use a Table Value Constructor:
SELECT field1
FROM
( VALUES
('aa11'),('bb22'),('cc33')
) AS x (field1)
WHERE field1 NOT IN
( SELECT field1 FROM tblList ) ;
Tested at SQL-Fiddle

Related

How to get also the not existing values

I've got a query like this
select column, count(*)
from mytable
where column in ('XXX','YYY','ZZZ',....)
group by column;
But I want also to get a row for values the aren't in the table.
Let's suppose that 'ZZZ' doesn't exist in mytable, I'd like to get:
COLUMN COUNT(*)
XXX 3
YYY 2
ZZZ 0 (or NULL)
Oracle version 10g
Thanks in advance
Mark
In general, you would need to have a second table which contains all the possible column values whose counts you want to appear in the output. For demo purposes only, we can use a CTE for that:
WITH vals AS (
SELECT 'XXX' AS val UNION ALL
SELECT 'YYY' UNION ALL
SELECT 'ZZZ'
)
SELECT t1.val, COUNT(t2.col) AS cnt
FROM vals t1
LEFT JOIN mytable t2
ON t2.col = t1.val
GROUP BY
t1.val;

UNION two tables with conditions from the first

I have a union on the same table [MyTable] so I can select certain values as the top 5, the logic of which I'm excluding here to simplify the question (I hope):
The first table I alias as tbl1 - can I reference this alias somehow after the UNION statement so that I can exclude the results from it?
I tried like so but it doesn't recognise tbl1
SELECT top 5 tbl1.Id, tbl1.Description, 'first'
FROM (
-- query [MyTable] joined with others to get particular result set
) as tbl1
UNION
SELECT tbl2.Id, tbl2.Description, 'second'
FROM [MyTable] as tbl2 WHERE tbl2.Id NOT IN
(SELECT Id FROM tbl1)
Or do I just have to redo the first query in the 2nd half in order to get those Id's to exclude?
I'm using SQL Server 2012 for this.
You can also use a temp table for the same purpose based on your requirement. See the difference here.
SELECT TOP 5 tbl1.Id, tbl1.Description, 'first' INTO #tbl1
FROM (
-- query [MyTable] joined with others to get particular result set
)
SELECT * FROM #tbl1
UNION ALL
SELECT tbl2.Id, tbl2.Description, 'second'
FROM [MyTable] AS tbl2
WHERE tbl2.Id NOT IN (SELECT Id FROM #tbl1)
Use a CTE:
WITH cte AS (
SELECT top 5 tbl1.Id, tbl1.Description, 'first'
FROM (
-- query [MyTable] joined with others to get particular result set
) as tbl1
)
SELECT * FROM cte
UNION ALL
SELECT tbl2.Id, tbl2.Description, 'second'
FROM [MyTable] as tbl2 WHERE tbl2.Id NOT IN (SELECT Id FROM cte)

Returning not found values in query

I'm working on a project, and I have a list of several thousand records that I need check. I need to provide the list of the ones NOT found, and provide the query I use to locate them so my superiors can check their work.
I'll admit I'm relatively new to SQL. I don't have access to create temporary tables, which is one way I had thought of to do this.
A basic idea of what I'm doing:
select t.column1, t.column2
from table1 t
where t.column1 in ('value1','value2','value3')
If value1 and value3 are in the database, but value2 is not, I need to display value2 and not the others.
I have tried ISNULL, embedding the query, and trying to select NOT values from the query.
I have searched for returning records not found in a query on Google and on this site, and still found nothing.
I have tried something similar:
First create a table which will contain all such values that you need.
lets say
create table table_values(values varchar2(30));
then try the in clause as below:
select * from table_values tv where tv.value not in (select t.column1
from table1 t);
this will return the values needed.
In SQL Server 2008, you can make derived tables using the syntax VALUES(...)(...)(...), e.g.
select v.value
from (
values ('value1'),('value2'),('value3')
) v(value)
left join table1 t on t.column1 = v.value
where t1.column1 is null
Notes:
Each (...) after VALUES is a single row, and you can have multiple columns.
The v(value) after the derived table is the alias given to the table, and column name(s).
LEFT JOIN keeps the values from the derived table v even when the record doesn't exist in table1
Then, we keep only the records that cannot be matched, i.e. t1.column1 is null
I've switched the first column in your select to the column from v. column2 is removed because it is always null
solution might work in Oracle where dual is single row single column table. You need
one table where you can make virtual select of desired values!
WARNING as I don't have access to db I never tested query below.
SELECT tab_all.col_search, t.column1, t.column2
FROM
(
Select value1 AS col_search from dual
union all
Select value2 from dual
union all
Select value3 from dual
) tab_all left join table1 t
on col_search = t.column1
WHERE t.column1 is null;
I belive sqlserver equivalent of Oracle's
SELECT value1 FROM dual is
SELECT value1 OR SELECT 'value1'.
So try
SELECT tab_all.col_search, t.column1, t.column2
FROM
(
Select value1 AS col_search
union all
Select value2 AS col_search
union all
Select value3 AS col_search
) tab_all left join table1 t
on col_search = t.column1
WHERE t.column1 is null;
As I am not sqlserver person might be that
RichardTheKiwi version of Oracle's select from dual is better.

Count rows in more than one table with tSQL

I need to count rows in more than one table in SQL Server 2008. I do this:
select count(*) from (select * from tbl1 union all select * from tbl2)
But it gives me an error of incorrect syntax near ). Why?
PS. The actual number of tables can be more than 2.
In case you have different number of columns in your tables try this way
SELECT count(*)
FROM (
SELECT NULL as columnName
FROM tbl1
UNION ALL
SELECT NULL
FROM tbl2
) T
try this:
You have to give a name to your derived table
select count(*) from
(select * from tbl1 union all select * from tbl2)a
I think you have to alias the SELECT in the FROM clause:
select count(*)
from
(
select * from tbl1
union all
select * from tbl2
) AS SUB
You also need to ensure that the * in both tables tbl1 and tbl2 return exactly the same number of columns and they have to be matched in their type.
I don't like doing the union before doing the count. It gives the SQL optimizer an opportunithy to choose to do more work.
AlexK's (deleted) solution is fine. You could also do:
select (select count(*) from tbl1) + (select count(*) from tbl2) as cnt

TSQL: query with optional join

I have a search ui with 3 all optional search criteria.
2 of them are simple criteria for a where statement, that I should be able to solve with this: Stored Procedure with optional "WHERE" parameters.
The last criterion is using full text search where I join the result from ContainsTable. Is there some trick I can use to put everything in one stored procedure? Or should I make two queries, one with the full text search and one without?
Edited: I should have put my query here as well, sorry here it is
select Table1.* from Table1
join
(
select [Key], SUM(Rank) as Rank from
(
SELECT [Key], Rank*3 as Rank FROM Table1ShortSearch(#Keywords) union all
SELECT [Key], Rank*2 as Rank FROM Table1LongSearch(#Keywords)
) as RankingTbl
group by [Key]
) as r
on Table1.Id = r.[Key]
where ( #Status_Id Is Null Or Status_Id = #Status_Id )
order by r.Rank Desc
Thanks.
you can put everything in one stored procedure and have an IF statement - http://msdn.microsoft.com/en-us/library/ms182717.aspx
Original Answer:
You can use an EXISTS function like so:
Select ..
From ..
Where ( #Status_Id Is Null Or Status_Id = #Status_Id )
And (#Date Is Null Or [Date] = #Date )
And (#Criteria Is Null Or Exists(
Select 1
From ContainsTable(TableName, Column1,...,ColumnN, #Criteria..) As SearchTable1
Where SearchTable1.PK = OuterTable.PK
) )
After question revision:
The revised query is of a completely different nature than the original query. In the original query, you simply wanted to return results from Table1 and additionally filter those results if #Keywords was not null. In this query, you are outputting to the SELECT clause the freetext ranking. What would display for the ranking if #Keywords was passed as null?
If freetext ranking is not needed and you simply want to return results if either of the searches on #Keywords finds something, then you would do something like:
Select ...
From Table1
Where ( #Status_Id Is Null Or Status_Id = #Status_Id )
And ...
And (
#Keywords Is Null
Or Exists (
Select 1
From Table1ShortSearch(#Keywords) As T1
Where T1.Key = Table1.Key
)
Or Exists (
Select 1
From Table1LongSearch(#Keywords) As T2
Where T2.Key = Table1.Key
)
)
If you want to display the freetext ranking then your original query or perhaps a CTE would be the solution however you will need to use a Left Join to your subquery if you want to account for #Keywords being null. That would make your query read:
Select ...
From Table1
Left Join (
Select [Key], Sum(Rank) as Rank
From (
Select [Key], Rank*3 As Rank
From Table1ShortSearch(#Keywords)
Union All
Select [Key], Rank*2 As Rank
From Table1LongSearch(#Keywords)
) As RankingTbl
Group By [Key]
) as R
On R.[Key] = Table1.Id
Where ( #Status_Id Is Null Or Status_Id = #Status_Id )
And ...
And ( #Keywords Is Null Or R.Key Is Not Null )
Order By R.Rank Desc