SQL: always return true from `IN` condition - mysql

How to make IN condition always return true just like WHERE 1, I tried null but didn't work:
WHERE X IN (NULL)
Is there a way to alway make IN returns true and accept all rows?
return true from something like the following:
where X in ("Any value here to alway return true")

The best you could do is to include the column being compared:
where x in (x)
However, this does not include NULL values. In fact, there is no way you can make this return true:
where NULL in ( . . . )
You could revise this to:
where coalesce(x, '') in (coalesce(x, '')

One way is to use LEFT JOIN :
select t.*
from table t left join
( . . . ) tt
on tt.x = t.x;

Related

How to remove an element in jsonb integer array in PostgreSQL

On Postgres, in a table called "photo" I have a jsonb column called "id_us" containing a json integer array, simply like this one [1,2,3,4]
I would like to find the query to remove the element 3 for example.
The closer I could get is this
SELECT jsonb_set(id_us, ''
, (SELECT jsonb_agg(val)
FROM jsonb_array_elements(p.id_us) x(val)
WHERE val <> jsonb '3')
) AS id_us
FROM photo p;
Any idea how to solve this?
Thank you!
You can use a subquery containing JSONB_AGG() function while filtering out the index value 3(by starting indexing from 1) such as
WITH p AS
(
SELECT JSONB_AGG(j) AS js
FROM photo
CROSS JOIN JSONB_ARRAY_ELEMENTS(id_us)
WITH ORDINALITY arr(j,idx)
WHERE idx != 3
)
UPDATE photo
SET id_us = js
FROM p
Demo
Edit : If you need to remove the value but not index as mentioned in the comment, just use the variable j casted as numeric
WITH p AS
(
SELECT JSONB_AGG(j) AS js
FROM photo
CROSS JOIN JSONB_ARRAY_ELEMENTS(id_us)
WITH ORDINALITY arr(j,idx)
WHERE j::INT != 18
)
UPDATE photo
SET id_us = js
FROM p
Demo
P.S: using JSONB_SET(), the comma-seperated place for the removed element along with quotes will still remain in such a way that in the following
WITH p AS
(
SELECT ('{'||idx-1||'}')::TEXT[] AS idx
FROM photo
CROSS JOIN JSONB_ARRAY_ELEMENTS(id_us)
WITH ORDINALITY arr(j,idx)
WHERE j::INT = 18
)
UPDATE photo
SET id_us = JSONB_SET(id_us,idx,'""')
FROM p;
SELECT * FROM photo;
id_us
-----------------
[127, 52, "", 44]
I've run across a similar issue, and it stems from the - operator. This operator is overloaded to accept either text or integer, but acts differently for each type. Using text will remove by value, and using an integer will remove by index. But what if your value IS an integer? Well then you're shit outta luck...
If possible, you can try changing your jsonb integer array to a jsonb string array (of integers), and then the - operator should work smoothly.
e.g.
'{1,2,3}' - 2 = '{1,2}' -- removes index 2
'{1,2,3}' - '2' = '{1,2,3}' -- removes values == '2' (but '2' != 2)
'{"1","2","3"}' - 2 = '{"1","2"}' -- removes index 2
'{"1","2","3"}' - '2' = '{"1","3"}' -- removes values == '2'

Doctrine - Not equal to some value

I want to detect id that are not equal to 1,2,3 or NULL . here is my query:
$qb = $this->_em->createQueryBuilder()
->select('u.cityId')
->from('.....\Entities\Cities', 'u')
->where("u.cityId is null OR u.cityId NOT IN (:parentType) ")
->setParameter('parentType' , "2,3,10");
$qb = $qb->getQuery();
return $qb->getResult();
Although it shows me id which are NULL or not equal to 2 and another values. It's not restrict 3,10. Any suggestion?
You need to pass an array. Try this:
->setParameter('parentType' , array(2,3,10) );
Instead of:
->setParameter('parentType' , "2,3,10");
Hope this help

NULL != NULL in mysql query

I am trying to do a query that sees if fields are equivalent. However, whenever the field is NULL it returns a false result. I even tried doing the same thing with the column itself:
SELECT * FROM `mturk_completion` WHERE (`mturk_completion`.`imdb_url` =
`mturk_completion`.`imdb_url` AND `mturk_completion`.`worker_id` = 'A3NF84Q37D7F35' )
And it only returns results where the column is not NULL. Why is this so, and how do I get around it?
Your title is absolutely correct for any SQL implementation (not just MySQL). NULL is not equal to anything (including another NULL).
You need to use explicit IS NULL check or COALESCE() function (or its RDBMS-dependent alternatives) to set some default value in case of NULL.
Your comparison of mturk_completion.imdb_url to itself is redundant and should always return True, except when mturk_completion.imdb_urlis Null, in which case it will return Null.
That's because the operator = returns either True, False when comparisons can be made or Null, when either of the two operators is Null
Try this to illustrate the situation.
SELECT 1 = NULL; -- returns NULL
SELECT 1 != NULL; -- also return NULL
SELECT ISNULL(1 = NULL); -- returns 1
SELECT ISNULL(1 != NULL); -- returns 1
If you rewrite your query like below, your problems with ignoring NULLs will go away:
SELECT * FROM `mturk_completion` WHERE worker_id = 'A3NF84Q37D7F35'
I think you can use
(table.Field = table2.Field OR COALESCE(table.Field, table2.Field) IS NULL)

WHERE Clause only IF NOT NULL

I need help with my SELECT.
I got a field that can be NULL and in it there is stored a foreign-key.
SELECT * FROM beerImage WHERE beerBRewID = brewID AND beerBrandID = beerID <--- this can be NULL
So if it's NULL nothing happens.
How can I check if beerID is NOT NULL so I can use "beerBrandID = beerID"?
You probably need something like this:
First example:
SELECT * FROM beerImage WHERE beerBRewID = brewID AND (beerID IS NULL OR beerBrandID = beerID)
Second Example:
SELECT * FROM beerImage WHERE beerBRewID = brewID AND beerID IS NOT NULL AND beerBrandID = beerID
The first example will allow you to show records which have beerID null along with the beers which beerBrandID is equal to beerID (both).
The second one will return exactly beers which correspond to beerBrandID (excluding NULL beerIDs).
How about using with CASE statement in where clause like
WHERE
CASE WHEN beer.id IS NOT NULL
THEN beer.brand_id = 12345
ELSE TRUE
END
If you want to include records where there's no match, you need an outer join
SELECT beer.id AS beerID,
beer.barrelID AS barrelID,
beer.imageID AS imageID,
beer.title AS title,
beer.map AS map,
beer.longitude AS longitude,
beer.latitude AS latitude,
brand.name AS brandName,
brew.type AS brewType,
image.name AS imageName,
variation.name AS variationName
FROM brand, brew, image, beer
LEFT OUTER JOIN variation ON variation.ID = beer.VariationID
WHERE beer.id = %s
AND md5(beer.memberID) = %s
AND beer.review = 1
AND brand.ID = beer.brandID
AND brew.ID = beer.brewID
AND image.ID = beer.imageID
To check for null / not null, use IS NULL / IS NOT NULL
AND beerID IS NOT NULL
You can use "IS NULL" or "IS NOT NULL" MySQL comparison functions.
Read more about this here:
http://dev.mysql.com/doc/refman/5.0/en/working-with-null.html
http://dev.mysql.com/doc/refman/5.0/en/comparison-operators.html#operator_is-null

MySQL Left Join, SELECT a field either from one or the other if null

I am trying to LEFT JOIN 2 tables. which is working out fine. But i am getting back two sets of fields named setting_value. iam trying to get tblSettings.setting_value only if tblAgencySettings.setting_value is NULL. How would i go about doing this? I know i can rename the fields, then in PHP i can check the tblAgencySettings.setting_value and if NULL then grab the tblSettings.setting_value but i prefer to keep this at MySQL.
SELECT `tblSettings`.`id`, `tblSettings`.`setting_name`,
`tblSettings`.`setting_value`, `tblAgencySettings`.`setting_value`
FROM `tblSettings` LEFT JOIN `tblAgencySettings`
ON `tblSettings`.`id` = `tblAgencySettings`.`setting_id`
AND `tblAgencySettings`.`agency_id` = '1'
WHERE `tblSettings`.`changeable` = '1'
slight issue i just noticed. i failed to mention this. if tblAgencySettings.setting_value does have a value. but changeable is not 1 then just select tblSettings.setting_value
Just add a COALESCE:
SELECT `tblSettings`.`id`, `tblSettings`.`setting_name`,
COALESCE(`tblAgencySettings`.`setting_value`, `tblSettings`.`setting_value`)
FROM `tblSettings` LEFT JOIN `tblAgencySettings`
ON `tblSettings`.`id` = `tblAgencySettings`.`setting_id`
AND `tblAgencySettings`.`agency_id` = '1'
WHERE `tblSettings`.`changeable` = '1'
The COALESCE function returns the first non-NULL value you give it so this:
COALESCE(`tblAgencySettings`.`setting_value`, `tblSettings`.`setting_value`)
Will be tblAgencySettings.setting_value if that's not NULL and tblSettings.setting_value if tblAgencySettings.setting_value is NULL.
If tblAgencySettings.setting_value can also be zero and you want to ignore that as well as NULL, then you could use this instead of the COALESCE above:
COALESCE(
IF(`tblAgencySettings`.`setting_value` = 0, NULL, `tblAgencySettings`.`setting_value`),
`tblSettings`.`setting_value`
)
The IF returns the second argument if the first is true and the third if the first argument is false so the above use converts zero to NULL. Or, you could go all the way to a CASE statement:
case
when `tblAgencySettings`.`setting_value` = 0 then `tblSettings`.`setting_value`
when `tblAgencySettings`.`setting_value` IS NULL then `tblSettings`.`setting_value`
else `tblSettings`.`setting_value`
end
Change your SQL Statement to this:
SELECT `tblSettings`.`id`, `tblSettings`.`setting_name`,
CASE WHEN `tblSettings`.`setting_value` IS NULL THEN `tblAgencySettings`.`setting_value`
ELSE `tblSettings`.`setting_value` END AS `setting_value`
FROM `tblSettings` LEFT JOIN `tblAgencySettings`
ON `tblSettings`.`id` = `tblAgencySettings`.`setting_id`
AND `tblAgencySettings`.`agency_id` = '1'
WHERE `tblSettings`.`changeable` = '1'
Here's a link to MYSQL CASE Statement for your reference.