MySQL query executes fine, but returns (false) empty result set when using != NULL? - mysql

I have the following result set, that I'm trying to drill down
+----+---------+---------------+---------------------+----------------------+---------------+-----------+------------------+------------------+
| id | auth_id | trusts_number | buy_sell_actions_id | corporate_actions_id | fx_actions_id | submitted | created_at | updated_at |
+----+---------+---------------+---------------------+----------------------+---------------+-----------+------------------+------------------+
| 2 | 6 | N100723 | 2 | NULL | NULL | 0 | 08/05/2015 11:30 | 08/05/2015 15:32 |
| 5 | 6 | N100723 | NULL | NULL | 1 | 0 | 08/05/2015 15:10 | 08/05/2015 15:10 |
| 6 | 6 | N100723 | NULL | NULL | 2 | 1 | 08/05/2015 15:12 | 08/05/2015 15:41 |
+----+---------+---------------+---------------------+----------------------+---------------+-----------+------------------+------------------+
This result set is generated with the query
SELECT * FROM actions WHERE auth_id = 6 AND trusts_number = 'N100723'
I also want to get rid of any field with fx_actions is NULL, so I change the query to
SELECT * FROM actions WHERE auth_id = 6 AND trusts_number = 'N100723' AND fx_actions_id != NULL
However this returns an empty result set. I've never used "negative" query parameters in MySQL before, so I'm not sure if they should take on a different syntax or what?
Any help would be much appreciated.

Normal comparison operators don't work well with NULL. Both Something = NULL and Something != NULL will return 'unknown', which causes the row to be omitted in the result. Use the special operators IS NULL and IS NOT NULL instead:
SELECT * FROM actions
WHERE auth_id = 6
AND trusts_number = 'N100723'
AND fx_actions_id IS NOT NULL
Wikipedia on NULL and its background

Because null isn't a value, you should use IS NOT NULL

Related

Check for ranges overlapping database side with coalesce

I can't figure out how to check on database side if two ranges, that can handle null values (ex. range A: null - null range B: 3 - 10), overlaps.
In this case, those two ranges overlaps because in my code null - null it's equal to -∞ and +∞ so 3 - 10 is inside -∞ - +∞.
The problem is that i need to build a query that returns all the records from my table stock_rule that have a range that overlaps with the stock_rule record that i'm trying to create.
If the count is major than zero then i can't save the record.
I'm trying to achieve that using COALESCE function (MySQL 8.0) in this way:
COALESCE(rule.min_price, 0)<=COALESCE(:minPrice, rule.min_price,0) AND
COALESCE(rule.max_price, 0)<=COALESCE(:minPrice, rule.max_price, 0) AND
COALESCE(rule.min_price, 0)<=COALESCE(:maxPrice, rule.min_price,0) AND
COALESCE(rule.max_price, 0)<=COALESCE(:maxPrice, rule.max_price, 0) AND
COALESCE(:minPrice, 0)>=COALESCE(rule.min_price, :minPrice, 0) AND
COALESCE(:maxPrice,0)<=COALESCE(rule.min_price, :maxPrice, 0) AND
COALESCE(:minPrice,0)>=COALESCE(rule.max_price, :minPrice, 0) AND
COALESCE(:maxPrice, 0)<=COALESCE(rule.max_price, :maxPrice, 0)
I guess something like this would work...
DROP TABLE ranges;
CREATE TABLE ranges
(id seriAL PRIMARY KEY
,range_start INT NULL
,range_end INT NULL
);
INSERT INTO ranges VALUES
(1,NULL,NULL),
(2,3,10),
(3,12,NULL),
(4,NULL,20),
(5,10,11);
SELECT *
FROM ranges x
JOIN ranges y
ON y.id <> x.id
AND COALESCE(x.range_start,0) <= y.range_end
AND COALESCE(x.range_end,(SELECT MAX(range_end) FROM ranges)) >= y.range_start;
+----+-------------+-----------+----+-------------+-----------+
| id | range_start | range_end | id | range_start | range_end |
+----+-------------+-----------+----+-------------+-----------+
| 1 | NULL | NULL | 2 | 3 | 10 |
| 4 | NULL | 20 | 2 | 3 | 10 |
| 5 | 10 | 11 | 2 | 3 | 10 |
| 1 | NULL | NULL | 5 | 10 | 11 |
| 2 | 3 | 10 | 5 | 10 | 11 |
| 4 | NULL | 20 | 5 | 10 | 11 |
+----+-------------+-----------+----+-------------+-----------+
mysql>

Using Case When to Split 1 Column Into Many While Ignoring Null Values

I am fairly new to SQL and have tried many searches but cannot accomplish what I want.
I have custom field values that are contained in one table and column, each custom field gets its own id, but the stored value is in one column.
I am trying to get 1 column for each custom field with its associated value, here is my query:
SELECT PRODUCT.id AS ProductId, PRODUCT.num AS ProductNumber,
CASE WHEN customvarcharlong.customfieldid = '6' THEN customvarcharlong.info
END AS OEM1Name,
CASE WHEN customvarcharlong.customfieldid = '7' THEN customvarcharlong.info
END AS OEM1NumbersA
FROM product
JOIN customvarcharlong ON product.id=customvarcharlong.recordid
JOIN customfield ON customvarcharlong.customfieldid=customfield.id
WHERE PRODUCT.activeFlag = TRUE
ORDER BY PRODUCT.id
My problem is that I get a row for every custom field that has a value, and the case statement simply returns NULL for each that does not match the customfieldid.
2 00007 NULL NULL
2 00007 NULL NULL
2 00007 NULL NULL
2 00007 NULL NULL
2 00007 NULL NULL
2 00007 Comp1 NULL
2 00007 NULL 1234
2 00007 NULL NULL
2 00007 NULL NULL
Here is my desired result:
2 00007 Comp1 1234
Using where or group by eliminates some of the data since it is on different rows. Is this possible? I have 48 custom fields to add so you can imagine getting it right will save a lot of work.
Thanks!
Edit to add sample data from customvarcharlong:
+--------+---------------+-------+----------+
| id | customFieldId | info | recordId |
+--------+---------------+-------+----------+
| 170887 | 171 | N | 1481 |
| 170888 | 172 | 3.03 | 1481 |
| 170889 | 173 | new | 1481 |
| 170890 | 170 | 0 | 1481 |
| 170891 | 5 | 0 | 1481 |
| 170892 | 6 | OEM1 | 1481 |
| 170893 | 7 | Num1 | 1481 |
| 170894 | 200 | 4184 | 1481 |
| 170895 | 120 | Truck | 1481 |
+--------+---------------+-------+----------+
As you can probably tell the issue is the recordid repeats for as many custom field values exist, and the customfieldid repeats on each recordid. I would like to get the info value on each row in it's own column for each recordid (recordid=productid).
You're working with an EAV data model. Essentially, you want a separate left join to the values table (customvarcharlong) for every attribute (customfieldid) you want to return for a given set of entities (product).
Try it this way:
SELECT PRODUCT.id AS ProductId,
PRODUCT.num AS ProductNumber,
cvcl6.info AS OEM1Name,
cvcl7.info AS OEM1NumbersA
FROM product
LEFT JOIN customvarcharlong cvcl6
ON product.id=cvcl6.recordid
AND cvcl6.customfieldid = '6'
LEFT JOIN customvarcharlong cvcl7
ON product.id=cvcl7.recordid
AND cvcl7.customfieldid = '7'
WHERE PRODUCT.activeFlag = TRUE
ORDER BY PRODUCT.id

Unexpected NOT EQUAL TO NULL comparison in MySQL [duplicate]

This question already has answers here:
What's the difference between " = null" and " IS NULL"?
(4 answers)
Closed 5 years ago.
I have below table in MySQL.
city_data
+------+-----------+-------------+
| id | city_code | city_name |
+------+-----------+-------------+
| 4830 | BHR | Bharatpur |
| 4831 | KEP | Nepalgunj |
| 4833 | OHS | Sohar |
| 4834 | NULL | Shirdi |
+------+-----------+-------------+
and below query.
select id,city_code,city_name from city_data where city_code != 'BHR';
I was expecting 3 rows.
| 4831 | KEP | Nepalgunj |
| 4833 | OHS | Sohar |
| 4834 | NULL | Shirdi |
+------+-----------+-------------+
But getting only 2 rows.
| 4831 | KEP | Nepalgunj |
| 4833 | OHS | Sohar |
+------+-----------+-------------+
I am not able to understand why the row
| 4834 | NULL | Shirdi |
Not includes in the result of my query. The where condition(NULL != 'BHR') should have been passed.
Please, someone, help to clear the doubt.
According to MySQL Reference Manual, section 3.3.4.6: Working with NULL values the following is why:
Because the result of any arithmetic comparison with NULL is also
NULL, you cannot obtain any meaningful results from such comparisons.
In MySQL, 0 or NULL means false and anything else means true. The
default truth value from a boolean operation is 1.
This means that NULL != 'BHR' will evaluate to NULL, which in turn will mean false to MySQL. In order for the query to work as you want, you have to append OR city_code IS NULL to your query.
You cannot compare null values with !=, because it is null, use IS NULL predicate instead:
select id,city_code,city_name
from city_data
where city_code != 'BHR' OR city_code IS NULL;
It is not possible to test for NULL values with comparison operators, such as =, <, or <>. Therefore query is confusing and NULL record is being ignored. for more info go to https://www.w3schools.com/sql/sql_null_values.asp

Calculations of different columns in Mysql Query

I have a Table:-
+-----+--------------+--------------+----------+--------------------+---------------+-----------------+
| id | CustomerName | VideoQuality | IsActive | BufferedTime | ElapsedTime | TotalBufferTime |
+-----+--------------+--------------+----------+--------------------+---------------+-----------------+
| 139 | HotStar | 180 | Yes | 10.367167126617211 | 30.000000000 | NULL |
| 140 | HotStar | 1300 | NULL | 5.43524230876729 | 34.000000000 | NULL |
| 141 | HotStar | 1300 | NULL | 5.671054515212042 | 38.000000000 | NULL |
| 142 | HotStar | 1300 | NULL | 5.045639532902047 | 41.000000000 | NULL |
| 143 | HotStar | 1300 | NULL | 5.455747718023355 | 44.000000000 | NULL |
| 144 | HotStar | 1300 | NULL | 5.691559924468107 | 49.000000000 | NULL |
i want to calculate the columns BufferTime and ElapsedTime and insert that output to TotalBufferTime column but i want to skip the first row of the BufferTime.
So the fisrt calculation will be 5.43 + 30.000 second calculation will be 5.67 + 34.00 and so on.
I also have a column IsActive which shows the first row of Buffer time.
I want to do something like this :-
update RequestInfo SET `TotalBufferTime` = BufferedTime + ElapsedTime;
only thing i want to skip only the first row of the column buffered time.
Assuming you a field id that determines row order in your table, you can use a correlated subquery so as to get BufferedTime of previous row like this:
SELECT t1.CustomerName, t1.VideoQuality, t1.IsActive, t1.BufferedTime,
t1.ElapsedTime,
(SELECT t2.BufferedTime
FROM mytable AS t2
WHERE t2.td > t1.id
ORDER BY id LIMIT 1) + t1.ElapsedTime AS TotalBufferTime
FROM mytable AS t1
WHERE IsActive IS NULL
Edit:
To UPDATE you can use the following query:
SET #et = 0;
SET #ElapsedTime = NULL;
UPDATE RequestInfo
SET TotalBufferTime = CASE
WHEN (#et := #ElapsedTime) < 0 THEN NULL
WHEN #ElapsedTime := ElapsedTime THEN BufferedTime + #et
END
ORDER BY id;
The trick here is to use a CASE expression where the first WHEN clause is always evaluated (because it is the first one) but is never true. This way #et variable is initialized with the value of #ElapsedTime, i.e. the value of the previous record.
Demo here

Populate values from one table

I am trying to populate an empty table(t) from another table(t2) based on a flag field being set. He is my attempt below and the table data.
UPDATE 2014PriceSheetIssues AS t
JOIN TransSalesAvebyType2013Combined AS t2
SET t.`Tran_Type`=t2.`Tran_Type` WHERE t.`rflag`='1';
When I run the script, I receive (0) zero records affected.??
+-----------+----------------+-------------------+-------+-------+
| Tran_Type | RetailAvePrice | WholesaleAvePrice | Rflag | Wflag |
+-----------+----------------+-------------------+-------+-------+
| 125C | 992 | 650 | 1 | NULL |
| 2004R | 1500 | NULL | 1 | NULL |
| 4EAT | 1480 | 1999 | 1 | 1 |
+-----------+----------------+-------------------+-------+-------+
I think you should just do the following
INSERT INTO 2014PriceSheetIssues
( `fldX`, `fldY` )
VALUES (
SELECT `fldX`, `fldY`
FROM TransSalesAvebyType2013Combined
WHERE 2014PriceSheetIssues.`rflag`='1'
)
The select query gets the values and the insert puts it in the (empty) other table.