Selecting filtered rows with SQL - sql

I am constructing an SQL statement with some parameters. Finally, an SQL statement is created like
"select * from table where column1 = "xyz"".
But I also need the rows which are filtered with this statement. In this case they're rows which are not "xyz" valued in column1. More specifically, I am looking for something like INVERSE(select * from table where ...). Is it possible?
Edit: My bad, I know I can do it with != or operator. Here the case is, select statement may be more complex (with some ANDs and equal, greater operators). Let's assume a table has A,B,C and my SQL statement brings only A as result. But I need B and C while I only have the statement which brings A.

select * from table where column1 != 'xyz' or column1 is null;

If you want the other ones, do it like this:
select * from table where column1 <> "xyz"
column1 <> (differs from) "xyz"

To check if something is no equal you can use <> or even !=
SELECT *
FROM yourTable
WHERE <> 'xyz'
OR
SELECT *
FROM yourTable
WHERE != 'xyz'
Many database vendors support (see list) both versions of the syntax.

If you're retrieving both result sets at about the same time, and just want to process the xyz ones first, you could do:
select *,CASE WHEN column1 = "xyz" THEN 1 ELSE 0 END as xyz from table
order by CASE WHEN column1 = "xyz" THEN 1 ELSE 0 END desc
This will return all of the rows in one result set. Whilst xyz = 1, these were the rows with column1 = 'xyz'.

It was :
"select * from table where rowId NOT IN (select rowId from table where column1 = "xyz")
I needed a unique rowId column to achieve this.

Related

COUNT vs SELECT in SQL

What is better approach to check existence of an object in database?
select count(id) as count from my_table where name="searchedName";
OR
select id from my_table where name="searchedName";
And then check if count > 0 or the object is not null (ORM logic)
EDIT:
select id to be valid for Oracle.
The idea should be to that we only need to find one record in order to say that such record exists. This can be done with an EXISTS clause in standard SQL.
select exists (select * from mytable where name = 'searchedName');
returns true if the table contains a record with 'searchedName' and false otherwise.
If you want 0 for false and 1 for true instead (e.g. if the DBMS does not support booleans):
select case when exists (select * from mytable where name = 'searchedName')
then 1 else 0 end as does_exist;
You say you want this for Oracle. In Oracle you can use above query, but you'd have to select from the table dual:
select case when exists (select * from mytable where name = 'searchedName')
then 1 else 0 end as does_exist
from dual;
But for Oracle we'd usually use rownum instead:
select count(*) as does_exist
from mytable
where name = 'searchedName'
and rownum = 1; -- to find one record suffices and we'd stop then
This also returns 1 if the table contains a record with 'searchedName' and 0 otherwise. This is a very typical way in Oracle to limit lookups and the query is very readable (in my opinion).
I'd just call:
select id from my_table where name='searchedName';
Making sure there is an index for the name column.
And then check whether or not the result is empty.
Try with IF EXISTS (
if exists (select 1 from my_table where name = "searchedName")
begin
....
end

If value return the value. If a record not exists or when column is null, return 0 in Sql Server - different ways

I want to return 0 if there is no record or if the Column1 is null.
select #var = Column1
from myschema.mytable
where Id = #suppliedId;
select isnull(#var, 0);
The above code outputs 0 if if Column1 is null. Or if a row is not found
Whereas I tried to save some keystrokes but it resulted in,
select isnull(Column1, 0)
from myschema.mytable
where Id = #suppliedId;
The above code outputs null if Column1 is null or when there is no row
Any ideas what is wrong here ? Or is there any shorter way of writing the first code ?
You can do
SELECT #var = ISNULL(MAX(Column1), 0)
FROM myschema.mytable
WHERE Id = #suppliedId;
A scalar aggregate always returns a single row even if the underlying query returns zero rows.
Not really saving key strokes, but something like this could help :-)
SELECT TOP 1 tbl.field
FROM
(
SELECT 0 AS inx, 'no record' AS field
--if only one row is possible, than set '1' literally
UNION SELECT ROW_NUMBER() OVER(ORDER BY mytable.orderfield), ISNULL(mytable.Land,'is null')
FROM mytable
WHERE IDENTITY = #suppliedID
) AS tbl
ORDER BY tbl.inx DESC

What is the fastest/easiest way to tell if 2 records in the same SQL table are different?

I want to be able to compare 2 records in the same SQL table and tell if they are different. I do not need to tell what is different, just that they are different.
Also, I only need to compare 7 of 10 columns in the records. ie.) each record has 10 columns but I only care about 7 of these columns.
Can this be done through SQL or should I get the records in C# and hash them to see if they are different values?
You can write a group by query like this:
SELECT field1, field2, field3, .... field7, COUNT(*)
FROM table
[WHERE primary_key = key1 OR primary_key = key2]
GROUP BY field1, field2, field3, .... field7
HAVING COUNT(*) > 1
That way you get all records with same values for field 1 to 7, along with the number of occurrences.
Add the part between brackets to limit your search for duplicates, either with OR, or with IN (...).
IF EXISTS (SELECT Col1, Col2, ColEtc...
from MyTable
where condition1
EXCEPT SELECT Col1, Col2, ColEtc...
from MyTable
where condition2)
BEGIN
-- Query returns all rows from first set that are not column for column
-- also in the second (EXCEPT) set. So if there are any, there will be
-- rows returned, which meets the EXISTS criteria. Since you're only
-- checking EXISTS, SQL doesn't actually need to return columns.
END
No hash is necessary. Normal equality comparison is enough:
select isEqual = case when t1.a <> t2.a or t1.b <> t2.b bbb then 1 else 0 end
SELECT
CASE WHEN (a.column1, a.column2, ..., a.column7)
= (b.column1, b.column2, ..., b.column7)
THEN 'all 7 columns same'
ELSE 'one or more of the 7 columns differ'
END AS result
FROM tableX AS a
JOIN tableX AS b
ON t1.PK = #PK_of_row_one
AND t2.PK = #PK_of_row_two
Can't you just use the DISTINCT keyword? All duplicates will not be returned, so each row you receive is unique (and different from the others).
http://www.mysqlfaqs.net/mysql-faqs/SQL-Statements/Select-Statement/How-does-DISTINCT-work-in-MySQL
So you could make this query:
SELECT DISTINCT x,y,z FROM RandomTable WHERE x = something
Which will only return one row for each unique x,y,z combination.

Order by Maximum condition match

Please help me to create a select query which contains 10 'where' clause and the order should be like that:
the results should be displayed in order of most keywords(where conditions) matched down to least matched.
NOTE: all 10 condition are with "OR".
Please help me to create this query.
i am using ms-sql server 2005
Like:
Select *
from employee
where empid in (1,2,4,332,434)
or empname like 'raj%'
or city = 'jodhpur'
or salary >5000
In above query all those record which matches maximum conditions should be on top and less matching condition record should be at bottom.
SELECT *
FROM (SELECT (CASE WHEN cond1 THEN 1 ELSE 0 END +
CASE WHEN cond2 THEN 1 ELSE 0 END +
CASE WHEN cond2 THEN 1 ELSE 0 END +
...
CASE WHEN cond10 THEN 1 ELSE 0 END
) AS numMatches,
other_columns...
FROM mytable
) xxx
WHERE numMatches > 0
ORDER BY numMatches DESC
EDIT: This answer was posted before the question was modified with a concrete example. Marcelo's solution addresses the actual problem. On the other hand, my answer was giving priority to matches of specific fields.
You may want to try something like the following, using the same expressions in the ORDER BY clause as in your WHERE clause:
SELECT *
FROM your_table
WHERE field_1 = 100 OR
field_2 = 200 OR
field_3 = 300
ORDER BY field_1 = 100 DESC,
field_2 = 200 DESC,
field_3 = 300 DESC;
I've recently answered a similar question on Stack Overflow which you might be interested in checking out:
Is there a SQL technique for ordering by matching multiple criteria?
There are many options/answers possible. Best answer depends on size of the data, non-functional requirements, etc.
That said, what I would do is something like this (easy to read / debug):
Select * from
(Select *, iif(condition1 = bla, 1, 0) as match1, ..... , match1+match2...+match10 as totalmatchscore from sourcetable
where
condition1 = bla or
condition2 = bla2
....) as helperquery
order by helperquery.totalmatchscore desc
I could not get this to work for me on Oracle.
If using oracle, then this Order by Maximum condition match is a good solution.
Utilizes the case when language feature

How to return multiple values using case statement in oracle

I want to return multiple values from a query in oracle. For ex:
select count(*)
from tablename a
where asofdate='10-nov-2009'
and a.FILENAME in (case
when 1 = 1 then (select distinct filename from tablename
where asofdate='10-nov-2009' and isin is null)
else null
end);
I am getting error: ora 01427 single row subquery returns more than one row
Please advice.
Thanks, Deepak
A CASE statement cannot return more than one value, it is a function working on one value.
It is not required for your statement, this statement should work:
select count(*)
from tablename a
where asofdate='10-nov-2009'
and a.FILENAME in (select distinct filename
from tablename
where asofdate='10-nov-2009'
and isin is null);
Maybe you have another usage scenario in mind? Something like this:
Select *
From aTable
Where in CASE
WHEN Then
WHEN Then
ELSE END
Then using CASE may not be the right scenario. Maybe this helps you in the right direction:
Select *
From aTable
Where <Case1> and column1 in <Subselect1>
Or <Case2> and column1 in <Subselect2>
OR Not (<Case1> Or <Case2>) and column1 in <Subselect3>
But this will probably be quite some work for the optimizer ...
The distinct in your Case statement is attempting to return multiple values when only one is allowed, and your SELECT statement will only return one value in one row currently. If you're trying to get the count of each filename, do
SELECT FileName, Count(*)
FROM tablename
WHERE asofdate='10-nov-2009' and isin is null
GROUP BY FileName
Run this query:
select distinct filename from tablename
where asofdate='10-nov-2009' and isin is null
You'll see that it returns more than a single row which causes the ORA-01427.
For all I can tell, you're looking for something like:
select a.filename, count(*)
from tablename a
where a.asofdate = '10-nov-2009'
and exists (
select *
from tablename b
where b.isin is null
and a.asofdate = '10-nov-2009'
and a.filename = b.filename
)
group by a.filename
This would find the count of filenames for a day, for which there exists at least one row where isin is null.
If you edit your question and add an explanation of what you're looking for, you might get better answers.