Mysql: CONCAT_WS('', col) vs (col is null OR col=0) - mysql

Is there any difference between:
CONCAT_WS('', column)=''
AND
column is null OR column=0 *(and optionally 'OR column="" ')*
Is one of them better/faster...?
SELECT my_fields FROM my_table
WHERE my_terms_clause='anything' AND CONCAT_WS( '', nb_check ) = ''
OR
SELECT my_fields FROM my_table
WHERE my_terms_clause='anything' AND (p.nb_check is null OR p.nb_check = 0)
I usually use "column is null OR column=0", but I just want "expert's tips".

You should definitely use:
where col is null or column = 0
First, the intention of the code is much clearer. Second, the function call prevents the optimizer from using an index. To be honest,the or also makes it hard for the optimizer to use an index.
Probably the most efficient way to write the query is using union all:
SELECT my_fields
FROM my_table p
WHERE my_terms_clause = 'anything' AND p.nb_check is null
UNION ALL
SELECT my_fields
FROM my_table p
WHERE my_terms_clause = 'anything' AND p.nb_check = 0;
This can take advantage of an index on my_table(my_terms_clause, nb_check).

If a column holds the value of 0, then concat_ws() with empty string as separator will return '0', not '', so the 2 expressions are not equal. If you need to check for null or 0, then better use that version, that actually checks this condition.

Related

how to send "" instead of null in select * statement SQL

SELECT * FROM specifications
I want to send "" or "0" instead of null[if any column having null value],
can't use column-wise, more than 80 columns
As mentioned in the comments, the only way is to use COALESCE() OR ISNULL() as many times as the count (80) of your columns.
Just to make it easier, you can use the below query to generate that 80 statements for you.
SELECT CONCAT('ISNULL(',COLUMN_NAME ,',' ,
(CASE WHEN DATA_TYPE ='int' THEN '0'
WHEN DATA_TYPE ='varchar' THEN '' ELSE '' END) , ')' )
AS DERIVED_COLUMN
FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'specifications'
CHECK SAMPLE DEMO HERE
Note : This is under the assumption that all your column are of int or varchar datatype. If you have other datatypes, modify the CASE accordingly.

Why CONCAT does not insert text for the first time into mySQL table?

I am using UPDATE to insert simple text into a table where the field is MEDIUMTEXT (nullable field).
It is strange that it does not work when the field is null initially. If I manually enter at least a one character/space, then it's working.
I want to append the new text into existing text in the field.
UPDATE pen SET
PEN_STATUS = #PenStat,
PEN_STATUS_CHANGE_REASON = CONCAT(PEN_STATUS_CHANGE_REASON,'\n',ChangeDate,':',EmployeeID,':',ChangeReason)
WHERE PEN_ID = PenID;
Why is this?
CONCAT does not handle NULL values. As explained in the MySQL manual:
CONCAT() returns NULL if any argument is NULL.
You want to use COALESCE to handle that use case, like :
UPDATE pen SET
PEN_STATUS = #PenStat,
PEN_STATUS_CHANGE_REASON = CONCAT(
COALESCE(PEN_STATUS_CHANGE_REASON, ''),
'\n',
ChangeDate,
':',
EmployeeID,
':',
ChangeReason
)
WHERE PEN_ID = PenID;
Presumably, because something is NULL. Try using CONCAT_WS() instead:
UPDATE pen
SET PEN_STATUS = #PenStat,
PEN_STATUS_CHANGE_REASON = CONCAT_WS('\n',
PEN_STATUS_CHANGE_REASON,
CONCAT_WS(':', ChangeDate, EmployeeID, ChangeReason
)
)
WHERE PEN_ID = PenID;
CONCAT_WS() ignores NULL arguments. Plus, the separator only needs to be listed once.

Mysql and between\in range condition

We have x2 columns min and max. Each can be null or integer. When we start search throw table we cannot use BETWEEN command... Question is, how to find in range with this conditions
value is greater then min (if it's not null)
and
value is less then max (if it's not null)
and
value is in range of min and max (if they BOTH not null)
value - our integer number. As you can see we cannot use BETWEEN command.
So NULL means no limit. You can still use BETWEEN:
select *
from mytable
where #value between coalesce(minvalue, #value) and coalesce(maxvalue, #value);
Or simply AND:
select *
from mytable
where #value >= coalesce(minvalue, #value)
and #value <= coalesce(maxvalue, #value);
Or the very basic AND and OR:
select *
from mytable
where (#value >= minvalue or minvalue is null)
and (#value <= maxvalue or maxvalue is null);
Use this:
WHERE col BETWEEN COALESCE(min, -2147483648) AND COALESCE(max, 2147483647)
According to your logic, if either the min or max be NULL, then the restriction should be ignored. In the above WHERE clause, if min be NULL then col will always be greater than the lower boundary, assuming that col is an integer. Similar logic applies to the max condition.
The large (and small) numbers you see represent the largest and smallest possible values for an integer in MySQL.
Without the option of using BETWEEN, I would recommend using a simple WHERE-AND clause.
If null values are not allowed, you should use the COALESCE function
http://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#function_coalesce
Returns the first non-NULL value in the list, or NULL if there are no non-NULL values.
SELECT *
FROM SCORES
WHERE score >= COALESCE(min_score, score)
AND score <= COALESCE(max_score, score)
Here is a sample fiddle I created
http://sqlfiddle.com/#!9/306947/2/0
My solution Yii2 AR like
$query
->joinWith(['vacancySalary'])
->andWhere([
'and',
'IF (vacancy_salary.min IS NULL, ' . $this->salaryMin . ', vacancy_salary.min) >= ' . $this->salaryMin,
'IF (vacancy_salary.max IS NULL, ' . $this->salaryMin . ', vacancy_salary.max) <= ' . $this->salaryMin
]);
Simple answer is use IF condition and proper values.
ADDED:
Another way to go
$query
->joinWith(['vacancySalary'])
->andWhere($this->salaryMin . ' BETWEEN IF(vacancy_salary.min IS NULL, 0, vacancy_salary.min) AND IF(vacancy_salary.max IS NULL, 0, vacancy_salary.max)');

mysql if not null, 0 or ""

SELECT *
FROM table WHERE id IN ('21')
AND (content_id IS NULL OR content_id = 0 OR content_id = '')
Is there a shorter way of writing this condition.
I have a int() column that could be either: NULL, 0 or EMPTY.
You can use IFNULL function in MySQL.
select ____
from tbl
where IFNULL(content_id, 0) = 0
I think the shorter way is this:
SELECT *
FROM table
WHERE id IN ('21')
AND COALESCE(content_id IN ('0', ''), 1)
content_id IN ('0', '') may assume these values:
True if content_id is either '0' or ''
Null if content_id IS Null
False otherwise.
If it's Null, COALESCE will return 1 here, which is equivalent to True.
You can try COALESCE:
SELECT * FROM table WHERE id IN ('21')
AND COALESCE(content_id,0) =0;

JPQL / SQL query: where like '%' include null values

I have a simple JPQL query. (But this applies also to an sql query..)
FROM DomainObj d where d.field1 like 'TEST%' and d.field2 like '%';
If the DB contains the following row:
1) field1 -> 'TEST'; field2 -> null
the query return nothing!
If the DB contains the following values:
2) filed1 -> 'TEST'; field2 -> ''
the query return the row!
How can I include also null values while searching for like '%' keeping the query as simple as possible (avoiding and/or clause?)
I'm implementing searching funcionality of an entity in the db.. and I also search by many fields at the same time..
Thank you
Marco
You can't directly use nulls in equality tests, because null is un-equal to everything, including itself. That's why there's the is null test, e.g:
select null = null -> null
select null <> null -> null
select 1 = null -> null
select 1 <> null -> null
select 1 + null -> null
essentially null is contagious, and will nullify anything it's compared to, or added in to.
So yes, you'll have to do
SELECT ... WHERE somefield LIKE '%...%' or somefield IS NULL
Try this:
...
and IFNULL(d.field2, '') like '%'
...
where ...
and (field2 = '' or field2 is null)
Note that the condition field2 like '%' is nonsensical because it matches any text except null. If you added or field2 is mull to it you would match everything, so logically you should just remove the condition on field2
Use IS NULL:
where d.field1 like 'TEST%' OR d.field2 IS NULL;
FROM DomainObj d where (d.field1 like 'TEST%' or d.field1 IS NULL) and (d.field2 like '%' or d.field2 IS NULL)