BigQuery SQL conditional IN - sql

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)

Related

Why is this ORDER BY Clause in SQL Statement not working

I ran into an old code in an application. ORDER BY is not working here. From the execution plan, it looks like the ORDER BY is not executed at all.
IF(1 = 1)
(
SELECT * FROM dbo.Table WHERE Column1= 'abc'
)
ELSE
(
SELECT * FROM dbo.Table
)
ORDER BY Column2
I know I can get it to work by refactoring this query like this.
But I am just curious why the ORDER BY is not getting executed in the above query at the first place.
IF(1 = 1)
BEGIN
SELECT * FROM dbo.Table WHERE Column1= 'abc' ORDER BY Column2
END
ELSE
BEGIN
SELECT * FROM dbo.Table ORDER BY Column2
END
The ORDER BY is working, but only for the ELSE clause. SQL Server allows this syntax:
(SELECT * FROM dbo.Table )
ORDER BY Column2
And that is how the code is being interpreted. The ORDER BY is part of the ELSE. And I should point out that the IF condition is true, so it is the THEN query that is being executed.
You can do a UNION ALL instead of the IF:
SELECT * FROM dbo.Table WHERE 1 = 1 AND Column1= 'abc'
UNION ALL
SELECT * FROM dbo.Table WHERE NOT (1 = 1)
ORDER BY Column2
(Not here, but IF condition null values might need to be handled
too.)

How to check result of a query using IF scripting in BigQuery?

I have a query and I want to check if the output has at least one row, if not , show some message like "No data". I have tried like described here : https://cloud.google.com/bigquery/docs/reference/standard-sql/scripting#if
WITH
cte1 AS (
SELECT id, name
FROM My_table
)
SELECT
* from cte1;
IF (SELECT COUNT(*) = 0 FROM cte1) THEN SELECT "No data"; END IF
You can do something like this:
WITH cte1 AS (
SELECT id, name
FROM My_table
)
SELECT id, name
FROM cte1;
UNION ALL
SELECT NULL, 'No Data'
FROM (SELECT 1 as x) x
WHERE NOT EXISTS (SELECT 1 FROM cte2);
Note: The subqueries need to return the same columns.

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

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;

SQL if statement within WHERE clause

I want to do the following query, how can I implement it?
SELECT * FROM table WHERE routeNum LIKE 'N10%'
-->if no rows return, WHERE clause change to routeName LIKE '&something%'
I think this will work for you:
WITH CTE AS (
SELECT 2 AS 'INDEX', * FROM table WHERE routeNum LIKE 'N10%'
UNION ALL
SELECT 1 AS 'INDEX', * FROM table WHERE routeNum LIKE '&something%'
)
SELECT *
FROM CTE
WHERE CTE.INDEX = (SELECT MAX(INDEX) FROM CTE)
As you have to choose between two result sets, you will need two queries, which will return two different sets and then, based on the 'index' which corresponds to the query that has run, you choose how to display your results.
Here is a SQLFiddle demo.
A possible solution
WITH cte AS
(
SELECT *
FROM routes
WHERE routeNum LIKE 'N10%'
)
SELECT * FROM cte
UNION ALL
SELECT * FROM routes
WHERE routeNum LIKE 'something else%'
AND NOT EXISTS
(
SELECT *
FROM cte
)
Here is SQLFiddle demo
WITH tmp AS
(
SELECT t.*,
CASE
WHEN routeNum LIKE 'N10%' THEN 1
WHEN routeNum LIKE '&something%' THEN 2
ELSE 3 END AS q
FROM table t
)
SELECT * FROM tmp t
WHERE q = CASE WHEN (SELECT COUNT(*) FROM tmp WHERE q = 1 ) > 0 THEN 1 ELSE 2 END

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;