Oracle SQL - convert select count(*) into zero or one - sql

I'm using Oracle and I want to turn the result from a select count into a "binary" 0/1 value ... 0 = 0 ... non-zero = 1. From what I read online, in MS SQL, you can cast it to a "bit" but Oracle doesn't appear to support that.
Here's my simple example query (the real query is much more complex). I want MATCH_EXISTS to always be 0 or 1. Is this possible?
select count(*) as MATCH_EXISTS
from MY_TABLE
where MY_COLUMN is not null;

This should be fastest... get at most one row.
SELECT COUNT(*) AS MATCH_EXISTS
FROM MY_TABLE
WHERE MY_COLUMN IS NOT NULL
AND rownum <= 1;

If you use an exists clause this should be faster for large tables because Oracle doesn't need to scan the whole table. As soon as there is one row, it can stop retrieving it:
select count(*) as match_exists
from dual
where exists (select *
from my_table
where my_column is not null);

Don't do a count(). For performance, use exists:
select (case when exists (select 1 as MATCH_EXISTS
from MY_TABLE
where MY_COLUMN is not null
)
then 1 else 0
end)
from dual;
This can be significantly faster.

You can use CASE WHEN:
SELECT CASE WHEN MATCH_EXISTS = 0 THEN 0
ELSE 1
END AS MATCH_EXISTS
FROM (SELECT COUNT(*) AS MATCH_EXISTS
FROM MY_TABLE
WHERE MY_COLUMN IS NOT NULL) AS t;
EDIT:
SELECT CASE WHEN COUNT(*) = 0 THEN 0
ELSE 1
END as MATCH_EXISTS
FROM MY_TABLE
WHERE MY_COLUMN IS NOT NULL;

Related

Counting the number of NULLs in a SQL Server Column

I have two queries like so:
SELECT MyId, MyColumn FROM MyTable WHERE MyColumn IS NULL;
SELECT count(MyColumn) as MyCount FROM MyTable WHERE MyColumn IS NULL;
The results I get are:
MyId MyColumn
10 NULL
Why is the count 0 always in the second query?
The COUNT() function ignores NULL values, and so the count in your second query will always be zero. Either count something else:
SELECT COUNT(*) AS MyCount
FROM MyTable
WHERE MyColumn IS NULL;
Or else count over the entire table using a CASE expression to explicitly count NULL values:
SELECT COUNT(CASE WHEN MyColumn IS NULL THEN 1 END) AS MyCount
FROM MyTable;
Count doesn't count null.
You need to do something like this, transform null to 1 then sum them:
SELECT SUM(CASE WHEN MyColumn IS NULL THEN 1 ELSE 0 END) AS count_nulls
FROM MyTable;
You can simply use count(1) rather than column name in the count function as it ignores null value which counting.
SELECT COUNT(1) AS MyCount
FROM MyTable
WHERE MyColumn IS NULL;
As noted, COUNT(SomeValue) just counts the number of non-nulls, so you actually needed COUNT(*).
But another way is to subtract the non-nulls from the total
SELECT COUNT(*) - COUNT(MyColumn) AS MyCount
FROM MyTable;
A WHERE is probably faster though, especially if you have an index on that column.

BigQuery SQL conditional IN

I have been trying to construct a conditional IN like below, but this gives me the scalar subquery produced more than one element error. How should I approach this type of query instead? The tables are not related.
select * from my_table
where my_table.my_col in (
case
when 1 = 1
then (select my_col from my_other_table_1)
else (select my_col from my_other_table_2)
end
)
Try this below-
select * from my_table
where my_table.my_col in (
SELECT
case
when 1 = 1 then my_col_1
else my_col_2
END
from my_other_table
)
As your other tables are not related, you can try this below logic-
select * from my_table
where
(1=1 and my_col IN (select my_col_1 from my_other_table_01)
OR
(3=3 and my_col IN (select my_col_2 from my_other_table_02)

What is the quickest way in Oracle SQL to find out if one or more duplicates exist in a table?

I'm looking to create a statement that stops and returns true the very second it finds a duplicate value on a column. I don't care what the value is and simply need to know whether a duplicate exists or not; nothing else.
I know i can write Select count(*) from myTable group by primary_id having count(*) > 1; but this goes through every single row of the table, whereas I want the query to stop as soon as it encounters a single case of a duplicate existing.
The best shot i've attempted with what i know is this:-
select 1 as thingy from dual outer_qry
where exists
(
select * from
(
select some_ID,
case when COUNT(*) > 1 then 'X' else 'N' end as TRIG
from myTable
group by some_ID
)INNER_QRY
where INNER_QRY.trig = outer_qry.dummy
);
However this takes 13 seconds and I doubt it takes that long to find the first duplicate.
Can anyone please suggest where my thinking is going wrong as, hopefully from my SQL, my assumption is that the EXISTS function will be checked for every row returned for the inner_qry, but this doesn't seem to be the case.
You would use exists. This returns all the duplicates:
select t.*
from mytable t
where exists (select 1
from mytable t t2
where t2.some_id = t.some_id and t2.rowid <> t.rowid
);
In Oracle 12c, you would add fetch first 1 row only. And it can take advantage of an index on mytable(some_id).
In earlier versions:
select 1 as HasDuplicate
from (select t.*
from mytable t
where exists (select 1
from mytable t t2
where t2.some_id = t.some_id and t2.rowid <> t.rowid
)
) t
where rownum = 1;
If this returns no rows, then there are no duplicates.
select * from table1 t1 natural join table1 t2 where t1.rowid < t2.rowid;
you can use this to understand which id is dublicate
select some_ID
from myTable
group by some_ID having count(*) >1

How to select a record if the query returns one row, or select no record if the query returns more rows?

I require to select a row if there is only one row exists, if there are more rows, it should select 0 rows.
If you're using PL/SQL, then selecting the column using select-into will throw a too_many_rows exception if there's more than one row returned:
declare
var table.column%type;
begin
select column
into var
from table
where ...;
end;
If you want to do this just using SQL, then you can do something like:
select *
from
(select s.*, count(*) over () c
from
(select *
from table
where ...
and rownum <= 2
) s
)
where c = 1
UPDATE
As DazzaL says in the comments, the reason for the rownum <= 2 restriction is to short-circuit the query if there's more than 2 rows in the result set. This can give significant performance benefits if the dataset is large.
I came up with this, just for the heck of it, using a CTE
With counter as
( select count(any_field) as cnt from your_query
)
SELECT
your_query
WHERE exists (SELECT cnt from Counter WHERE cnt=1)
1 row when there's 1 record - http://sqlfiddle.com/#!4/84c7b/2
0 rows when more than 1 rec - http://sqlfiddle.com/#!4/95c4a/1
EDIT
or if you want to avoid repeating the whole query... an example :
(using the schema from sqlfiddle http://sqlfiddle.com/#!4/6a2d8/117 )
With results as
( select * from montly_sales_totals
),
counter as
( SELECT count(name) as cnt FROM results
)
SELECT *
FROM results
WHERE exists (SELECT cnt from Counter WHERE cnt=5)
SELECT fld1, fld2
FROM (SELECT COUNT(*) over() cnt ,fld1, fld2 FROM tbl WHERE fld1 = 'key')
WHERE cnt = 1
I require to select a row if there is only one row exists, if there
are more rows, it should select 0 rows.
I assume the table contains only the row(s) you are interested to see (or not to see), in that case I would write something like
select *
from table1
where 1 = (select count(1)
from table1
)
In case you want to see only one row from a subset of results from your table, I would go for something like:
with t as ( select *
from table1
where [put here your condition]
)
select *
from t
where 1 = (select count(1)
from t
)
Try this:
SELECT f1,f2
FROM Table
WHERE (f1 = #f1) AND (f2=#f2) AND (f3=#f3)
GROUP BY f1,f2
HAVING (COUNT(*) = 1)
DECLARE COL_COUNT NUMBER;
BEGIN
COL_COUNT: = 0 ;
SELECT COUNT (1) INTO COL_COUNT FROM USER_TAB_COLUMNS WHERE TABLE_NAME = '(ur table name)';
IF COL_COUNT = 0 THEN
EXECUTE IMMEDIATE ('select * from dual') ;
END IF;
END;
Try this:
SELECT col1, col2 FROM
(SELECT count(id) as 'cnt', col1, col2 FROM table_name WHERE col1='value')
WHERE cnt=1;

Specified record in top of results list

Task: selecting specified record in top of results list
my ugly variant:
(select * from mytable where id = 42)
union all
(select * from mytable where id != 42 order by id)
besides of ansi query variant for mysql is also would be very interesting to me
There is no difference between ANSI and vendor SQL solutions
select *
from mytable
order by
CASE WHEN id = 42 THEN 0 ELSE 1 END, id
Note: there is no guaranteed or implied order to a table or SELECT without an ORDER BY clause
Assuming id is always positive, try:
select *
from mytable
order by CASE WHEN id = 42 THEN 0 ELSE id END