Case statement in sqlserver in where clause with else as always true - mysql

I have used the always true statement e.g. 1 = 1 in case statement of where clause in MYSQL with following syntax:
select * from tablename where
(case when tablefield is not null then
then tablefield = 'value'
else 1 = 1 end)
I want to know how can i use else 1 = 1 (always true statement) in sqlserver/tsql case statement in where clause.

you would not use case you would just write a multi conditional statement. In your case it would look like
Where (tablefield = 'value'
OR tablefield is null)

If you want to use the TSQL CASE function, you could do something like :
select * from tablename where 1 =
(case when tablefield is not null then
(case when tablefield = 'value' then 1 else 0 end)
else 1 end)
which could be simplified to :
select * from tablename where 1 =
(case when tablefield is null then 1 when tablefield = 'value' then 1
else 0 end)
You can leave out the "else 0" parts, as when no match is found, NULL is returned (which will not be equal to 1). i.e.:
select * from tablename where 1 =
(case when tablefield is not null then
(case when tablefield = 'value' then 1 end)
else 1 end)
select * from tablename where 1 =
(case when tablefield is null then 1 when tablefield = 'value' then 1 end)

Sorry I just mixed up the query,I was intended to ask for a condition when parameter variable is null instead of tablefield
In that case query may look like this :
select * from tablename where
(case when parameterfield_or_variable is not null then
then tablefield = 'value'
else 1 = 1 end)
or when using parameterfield for value
(case when parameterfield_or_variable is not null then
then tablefield = parameter_field_or_variable
else 1 = 1 end)
The answer as per asked question #KHeaney is right.
However the query in tsql/sqlserver as described in mysql, will be like this :
select * from tablename
where tablefield = #parameterfield
-- incase of comparing input parameter field with tablefield
or #parameter is null
so when #parameterfield will be null it will show all results otherwise it will restrict to only input value.
Thanks

You can try...
select * from tablename
where tablefield = isnull(#parameter, tablefield)

I know T-SQL and MySQL both provide COALESCE, which returns the first non-NULL value provided.
SELECT *
FROM tablename
WHERE (COALESCE(`tablefield`, 'value') = 'value')

Related

Not able to alias column name in nested case using sql query

In this code its able to alias each case statement separately like,
SELECT
id,
SUM(CASE
WHEN (a.place = 'CHN' AND a.salary = 20000)
THEN '1'
ELSE '0'
END) AS '20K Salary',
SUM(CASE
WHEN (a.place = 'CHN' and a.salary = 35000)
THEN '1'
ELSE '0'
END) AS '35K Salary'
FROM Employee a;
but when nested CASE statement is used,
SELECT
id,
SUM(CASE
WHEN (a.place = 'CHN')
THEN (CASE
WHEN a.salary = 20000
THEN '1'
ELSE '0'
END) AS '20K Salary',
(CASE
WHEN a.salary = 35000
THEN '1'
ELSE '0'
END) AS '35K Salary'
END)
FROM Employee a;
its not possible to execute the query
In the first set of code each case statement is part of the SELECT list (i.e. they are in a comma separated list following SELECT) so each returns a column. In the second set of code there is only one case statement in the SELECT list, the fact that it is nested has no impact on this. Also the syntax for the nested case isn't correct because the THEN part is followed by two expressions separated by commas which is not allowed.
Of course this is possible to do what you want. You want to create two columns, so each needs its own logic and its own alias:
SELECT id,
SUM(CASE WHEN a.place = 'CHN' AND a.salary = 20000 THEN 1 ELSE 0
END) as Salary_20K,
SUM(CASE WHEN a.place = 'CHN' AND a.salary = 35000 THEN 1 ELSE 0
END) as Salary_35K
FROM Employee a;
Note: Don't put numeric constants in single quotes. Only use single quotes for string and date constants.

Sum of 2 fetched columns in other column in Big query SQL

select x,
count(case when i='abc' then 1 else null end) as ele1,
count(case when i='def' then 1 else null end) as ele2,
sum(ele1+ele2) as sum1 from (INNER QUERY)
When i am using sum(ele1+ele2), it is throwing error that ele1 not found. How to fetch sum1 in the same query without using any other outer query?
You can't use alias as column name in select
select x,
count(case when i='abc' then 1 else null end) as ele1,
count(case when i='def' then 1 else null end) as ele2,
sum( ( case when i='abc' then 1 else null end ) +
( case when i='def' then 1 else null end ) ) as sum1
from (INNER QUERY)
You cannot use alias as a column name, but if your concern is in verboseness - in your particular case you can write something like below, which is easy readable and skinny enough (for BigQuery Legacy SQL)
SELECT
SUM( i ='abc' ) AS ele1,
SUM( i = 'def' ) AS ele2,
SUM( i IN ('abc', 'def') ) AS sum1
FROM (INNER QUERY)

Reduce the number of queries

I have seperate queries but i need to reduce the no so put all in one
select count(applicant_id) as registered from student_application where filter_status=0 AND
select count(applicant_id) as filer_select from student_application where filter_status=1 AND
select count(applicant_id) as filter_reject from student_application where filter_status=2
but this shows some errors
Use CASE expression.
Query
select
count(case when filter_status = 0 then applicant_id else null end) as registered,
count(case when filter_status = 1 then applicant_id else null end) as filer_select,
count(case when filter_status = 2 then applicant_id else null end) as filer_reject
from student_application;
SQL Fiddle
You could also use group_by, with the where clause if you're looking for a subset rather than all possible values of filter_status:
SELECT filter_status, COUNT(*)
FROM student_application
WHERE filter_status in (0, 1, 2)
GROUP BY filter_status;

MySql, Postgres, Oracle and SQLServer ignoring IS NOT NULL filter

While I was preparing an answer to one of our fellows here on SO I've encounter an odd situation, at least to me. The original question is here: Pivot Table Omitting Rows that Have Null values
I've modified the query to use max instead of group_concat in order to show the "problem" in all databases.
SELECT
id,
max(case when colID = 1 then value else '' end) AS fn,
max(case when colID = 2 then value else '' end) AS ln,
max(case when colID = 3 then value else '' end) AS jt
FROM tbl
GROUP BY id
The result of this query is this:
ID FN LN JT
1 Sampo Kallinen Office Manager
2 Jakko Salovaara Vice President
3 (null) Foo No First Name
The user asks to filter the row with id 3 because the field value is null.
When it seems pretty obvious that only it needs to do was to add a WHERE value IS NOT NULL constraint on that query to achieve what the user expect. It won't work.
So I start to test it on the other databases to see what happens (Queries with the WHERE CLAUSE)
SELECT
id,
max(case when colID = 1 then value else '' end) AS fn,
max(case when colID = 2 then value else '' end) AS ln,
max(case when colID = 3 then value else '' end) AS jt
FROM tbl
WHERE value is not null
GROUP BY id
Mysql: http://sqlfiddle.com/#!2/78395/1
Postgres: http://sqlfiddle.com/#!15/78395/1
SQLServer: http://sqlfiddle.com/#!6/78395/1
Oracle: http://sqlfiddle.com/#!4/78395/1
For my surprise the result was the same, none worked.
Then I tried a different version of the same query:
SELECT * FROM (
SELECT
id,
max(case when colID = 1 then value else '' end) AS fn,
max(case when colID = 2 then value else '' end) AS ln,
max(case when colID = 3 then value else '' end) AS jt
FROM tbl
GROUP BY id
) T
WHERE fn IS NOT NULL
AND ln IS NOT NULL
AND jt IS NOT NULL
Oracle: http://sqlfiddle.com/#!4/78395/2 WORKED
MySql: http://sqlfiddle.com/#!2/78395/2
Postgres: http://sqlfiddle.com/#!15/78395/2
SQLServer: http://sqlfiddle.com/#!6/78395/2
The only way I could make it work on all databases was with this query:
SELECT
id,
max(case when colID = 1 then value else '' end) AS fn,
max(case when colID = 2 then value else '' end) AS ln,
max(case when colID = 3 then value else '' end) AS jt
FROM tbl
WHERE NOT EXISTS (SELECT * FROM tbl b WHERE tbl.id=b.id AND value IS NULL)
GROUP BY id
So I ask:
What is happening here that except for that specific case on Oracle all other DBs seem to ignore the IS NOT NULL filter?
To omit the row from the result if any of the source rows for the same id has value IS NULL, a solution in Postgres would be to use the aggregate function every() or (synonym for historical reasons) bool_and() in the HAVING clause:
SELECT id
, max(case when colID = 1 then value else '' end) AS fn
, max(case when colID = 2 then value else '' end) AS ln
, max(case when colID = 3 then value else '' end) AS jt
FROM tbl
GROUP BY id
HAVING every(value IS NOT NULL);
SQL Fiddle.
Explain
Your attempt with a WHERE clause would just eliminate one source row for id = 3 in your example (the one with colID = 1), leaving two more for the same id. So we still get a row for id = 3 in the result after aggregating.
But since we have no row with colID = 1, we get an empty string (note: not a NULL value!) for fn in the result for id = 3.
A faster solution in Postgres would be to use crosstab(). Details:
PostgreSQL Crosstab Query
Other RDBMS
While EVERY is defined in the SQL:2008 standard, many RDBMS do not support it, presumably because some of them have shady implementations of the boolean type. (Not dropping any names like "MySQL" or "Oracle" ...). You can probably substitute everywhere (including Postgres) with:
SELECT id
, max(case when colID = 1 then value else '' end) AS fn
, max(case when colID = 2 then value else '' end) AS ln
, max(case when colID = 3 then value else '' end) AS jt
FROM tbl
GROUP BY id
HAVING count(*) = count(value);
Because count() doesn't count NULL values. In MySQL there is also bit_and().
More under this related question:
Is there any equivalent to Postgresql EVERY aggregate function on other RDBMS?
It works in Oracle because Oracle handles NULL incorrectly in that NULL and '' are the same. The other databases don't do this because it is wrong. NULL is unknown, versus '' which is just a blank, empty string.
So if your where clause said something like WHERE (fn IS NOT NULL or fn <> '') you would probably get further.
I think this is a case where a HAVING clause will do what you need.
SELECT id, max ... (same stuff as before)
FROM tbl
GROUP by id
HAVING fn IS NOT NULL
AND ln IS NOT NULL
AND jt IS NOT NULL

get count of two table fields in one query

I am trying to get the count of females and males in the gender field of a table.
Is there a way to get the count of each in one query?
Something like:
select * from table count(where gender = 'm') as total_males, count(where gender = 'f') as total_females;
or will it require two queries?
select count(*) from table where gender = 'm';
select count(*) from table where gender = 'f';
This is basically a PIVOT. MySQL does not have a pivot so you can use an aggregate function with a CASE statement to perform this:
select
sum(case when gender = 'm' then 1 else 0 end) Total_Male,
sum(case when gender = 'f' then 1 else 0 end) Total_Female
from yourtable
See SQL Fiddle with Demo
Or using COUNT:
select
count(case when gender = 'm' then 1 else null end) Total_Male,
count(case when gender = 'f' then 1 else null end) Total_Female
from yourtable;
See SQL Fiddle with Demo
Something like this will work:
SELECT SUM(IF(t.gender='m',1,0)) AS total_males
, SUM(IF(t.gender='f',1,0)) AS total_females
FROM mytable t
The "trick" here is that we are using a conditional test to return either a 0 or a 1 for each row, and then adding up the 0's and 1's. To make this a little more clear, I am using the SUM aggregate function rather than COUNT, although COUNT could be used just as easily, though we'd need to return a NULL in place of the zero.
SELECT COUNT(IF(t.gender='m',1,NULL)) AS total_males
, COUNT(IF(t.gender='f',1,NULL)) AS total_females
FROM mytable t
Consider that the two expressions in the SELECT list of this query:
SELECT COUNT(1)
, SUM(1)
FROM mytable t
Will return the same value.
If you want to avoid the MySQL IF function, this can also be done using the ANSI SQL CASE expression:
SELECT SUM( CASE WHEN t.gender = 'm' THEN 1 ELSE 0 END )) AS total_males
, SUM( CASE WHEN t.gender = 'f' THEN 1 ELSE 0 END )) AS total_females
FROM mytable t
select sum(case when gender='m' then 1 else null end) as total_males, sum(case when gender='f' then 1 else null end) as total_females from ...
Should work just fine!
If your only issue is to avoid two queries, you can always write two queries as subselects of one query.
Select (select 1 from dual) as one, (select 2 from dual) as two from dual
This would work for your scenario, too.