Sphinxsearch json values comparison - json

I''m working with JSON functionality in sphinx 2.2.2.INDEX table looks like:
mysql> SELECT subsite_min_cnt, version_content_cnt FROM mobile_collection;
+------------------------+-----------------------------------------------------------+
| subsite_min_cnt | version_content_cnt |
+------------------------+-----------------------------------------------------------+
| {"85":3,"75":4,"65":5} | {"10003":4,"10008":5,"10009":5,"11000":7,"1":1,"10000":3} |
| {"85":6,"75":4,"65":5} | {"46":1,"201":1,"11000":1,"10010":1} |
+------------------------+-----------------------------------------------------------+
And I work with two values from JSONs:
mysql> SELECT subsite_min_cnt.85 as a, version_content_cnt.10008 as b
FROM mobile_collection;
+------+------+
| a | b |
+------+------+
| 3 | 5 |
| 6 | NULL |
+------+------+
I try to compare these two value and here is what i get (the json_autoconv_numbers is equal to 1):
mysql> SELECT subsite_min_cnt.85 as a, version_content_cnt.10008 as b
FROM mobile_collection WHERE b IS NOT NULL and a < b;
ERROR 1064 (42000): sphinxql: syntax error, unexpected IDENT, expecting CONST_INT (or 3 other tokens) near 'b'
Or:
mysql> SELECT subsite_min_cnt.85 < version_content_cnt.10008 as b
FROM mobile_collection;
+------+
| b |
+------+
| 0 |
| 0 |
+------+
So, the question is: does comparison of two json values work in sphinxql? Or, maybe, I compare items in wrong way...

Despite json_autoconv_numbers = 1, the type conversion solved my problem:
mysql> SELECT integer(subsite_min_cnt.85) < integer(version_content_cnt.10008) as c, subsite_min_cnt.85, version_content_cnt.10008
FROM mobile_collection where c > 0;
+------+--------------------+---------------------------+
| c | subsite_min_cnt.85 | version_content_cnt.10008 |
+------+--------------------+---------------------------+
| 1 | 3 | 5 |
+------+--------------------+---------------------------+

Related

MySQL: Add Default Value to Joined Table when Row not Found

System info:
$ uname -srvm
Linux 5.15.0-56-generic #62-Ubuntu SMP Tue Nov 22 19:54:14 UTC 2022 x86_64
$ mysql --version
mysql Ver 8.0.31-0ubuntu0.22.04.1 for Linux on x86_64 ((Ubuntu))
I am very inexperienced with MySQL & have been looking for an answer to this for about half a week. I am working with two tables named character_stats & halloffame that I want to join in a query. They look like this:
mysql> SELECT name, level FROM character_stats;
+-----------+-------+
| name | level |
+-----------+-------+
| foo | 0 |
| bar | 0 |
| baz | 3 |
| tester | 4 |
| testertoo | 2 |
+-----------+-------+
mysql> SELECT * from halloffame;
+----+-----------+----------+--------+
| id | charname | fametype | points |
+----+-----------+----------+--------+
| 1 | bar | T | 0 |
| 2 | foo | T | 0 |
| 3 | baz | T | 0 |
| 4 | tester | T | 0 |
| 5 | testertoo | T | 0 |
| 6 | tester | D | 40 |
| 7 | tester | M | 92 |
| 8 | bar | M | 63 |
+----+-----------+----------+--------+
In my query, I want to display all the rows from character_stats & I want to join the points column from halloffame for fametype='M'. If there is no row for fametype='M', I want to set points to 0 for that character name, instead of omitting the entire row as is done in the following:
mysql> SELECT name, level, points FROM character_stats JOIN
-> (SELECT charname, points FROM halloffame WHERE fametype='M')
-> AS hof ON (hof.charname=name);
+--------+-------+--------+
| name | level | points |
+--------+-------+--------+
| tester | 4 | 92 |
| bar | 0 | 63 |
+--------+-------+--------+
So I want it to output this:
+-----------+-------+--------+
| name | level | points |
+-----------+-------+--------+
| foo | 0 | 0 |
| bar | 0 | 63 |
| baz | 3 | 0 |
| tester | 4 | 92 |
| testertoo | 2 | 0 |
+-----------+-------+--------+
I have tried to learn how to use IFNULL, IF-THEN-ELSE, CASE, COALESCE, & COUNT statements from what I have found in documentation & answers on stackoverflow.com. But as I said, I am very inexperienced & don't know how to implement them.
The following works on its own:
SELECT IFNULL((SELECT points FROM halloffame WHERE fametype='M'
AND charname='foo' LIMIT 1), 0) as points;
But I don't know how to join it to the character_stats table. The following would work if I knew how to get the value of character_stats.name before COALESCE is called:
SELECT name, level, 'M' AS fametype, points FROM character_stats
JOIN (SELECT COALESCE((SELECT points FROM halloffame WHERE
fametype='M' AND charname=name LIMIT 1), 0) AS points) AS hof;
According to Adding Default Values on Joining Tables I should be able to use CROSS JOIN, but I am doing something wrong as it still results in Unknown column 'cc.name' in 'where clause':
SELECT name, level, points FROM character_stats
CROSS JOIN (SELECT DISTINCT name FROM character_stats) AS cc
JOIN (SELECT COALESCE((SELECT points FROM halloffame WHERE
fametype='M' AND charname=cc.name LIMIT 1), 0) AS points) AS hof;
Some references I have looked at:
Returning a value even if no result
Usage of MySQL's "IF EXISTS"
Return Default value if no row found
MySQL.. Return '1' if a COUNT returns anything greater than 0
How do write IF ELSE statement in a MySQL query
Simple check for SELECT query empty result
Is there a function equivalent to the Oracle's NVL in MySQL?
MySQL: COALESCE within JOIN
Unknown Column In Where Clause With Join
Adding Default Values on Joining Tables
https://www.tutorialspoint.com/returning-a-value-even-if-there-is-no-result-in-a-mysql-query
I found that I can do the following:
SELECT name, level, COALESCE((SELECT points FROM
halloffame WHERE fametype='M' AND charname=name
LIMIT 1), 0) AS points FROM character_stats;
Though I would still like to know how to do it within a JOIN statement.

mysql regexp two words enclosed with any special characters

+-----+------+
| A | B |
+-----+------+
| gan | esh |
| dhi | nesh |
+-----+------+
I have a table like this. I want to check this with another table has column
+----------------+
| C |
+----------------+
| !!dhin!!esh |
| gan!!esh.. |
| $$$gan%%%esh.. |
+----------------+
The following query works fine
select * from table1 a, table2 b where c like concat('%',a,'%',b'%')
but what I want is starting, ending, middle should contain only non-alphanumeric. I am a newbie to regexp.
CONCAT("[^[:alnum:]]", a, "[^[:alnum:]]+", b, "[^[:alnum:]]")
Or perhaps
CONCAT("\\b", a, "[^[:alnum:]]+", b, "\\b")

MYSQL - Count items separated by comma or not

I have a tinytext field which can contain 3 differents value formatted as followed:
NULL
"X" or "Y" (where X and Y can be any number)
"A,B,C,D" (where A, B, C and D can be any number)
I want to query the table and count the number of items separated or not with a comma.
For example with these lines:
42
NULL
42,56,99
24,10090
Then the expected count would be 6.
I can't find the correct query.
Okay here's the test data:
mysql> create table t (f tinytext);
mysql> insert into t values ('42'), (null), ('42,56,99'), ('24,10090');
mysql> select * from t;
+----------+
| f |
+----------+
| 42 |
| NULL |
| 42,56,99 |
| 24,10090 |
+----------+
You can calculate how many numbers in the string as the difference in the length of the string and the string with commas removed (add 1 for the first number in the list).
mysql> select f, length(f), length(replace(f,',','')), 1+ length(f)-length(replace(f,',','')) from t;
+----------+-----------+---------------------------+----------------------------------------+
| f | length(f) | length(replace(f,',','')) | 1+ length(f)-length(replace(f,',','')) |
+----------+-----------+---------------------------+----------------------------------------+
| 42 | 2 | 2 | 1 |
| NULL | NULL | NULL | NULL |
| 42,56,99 | 8 | 6 | 3 |
| 24,10090 | 8 | 7 | 2 |
+----------+-----------+---------------------------+----------------------------------------+
So then use SUM() to get the total. SUM() ignores NULLs.
mysql> select sum(1+length(f)-length(replace(f,',',''))) from t;
+--------------------------------------------+
| sum(1+length(f)-length(replace(f,',',''))) |
+--------------------------------------------+
| 6 |
+--------------------------------------------+
This would be easier if you don't store comma-separated lists in a string.

INNER JOIN same value, but the difference is the other table are having extra word in front of the value

As I said in the title, or maybe my question is a little bit confusing. Here it is....
So, I want to combine 2 tables using INNER JOIN (ofcourse) with some difference.
This is my tables
Table 1, PK = steam_id
SELECT * FROM nmrihstats ORDER BY points DESC LIMIT 4;
+---------------------+----------------+--------+-------+--------+
| steam_id | name | points | kills | deaths |
+---------------------+----------------+--------+-------+--------+
| STEAM_0:1:88467338 | Alan14 | 50974 | 5438 | 12 |
| STEAM_0:0:95189481 | ? BlacKEaTeR ? | 35085 | 24047 | 316 |
| STEAM_0:1:79891668 | Lowell | 34410 | 44076 | 993 |
| STEAM_0:1:170948255 | Rain | 29780 | 30167 | 278 |
+---------------------+----------------+--------+-------+--------+
4 rows in set (0.01 sec)
Table 2, PK = authid
SELECT * FROM store_players ORDER BY credits DESC LIMIT 4;
+-----+-------------+---------------+---------+--------------+-------------------+
| id | authid | name | credits | date_of_join | date_of_last_join |
+-----+-------------+---------------+---------+--------------+-------------------+
| 309 | 1:88467338 | Alan14 | 15543 | 1475580801 | 1482260232 |
| 368 | 1:79891668 | Lowell | 10855 | 1475603908 | 1482253619 |
| 256 | 1:128211488 | Fuck[U]seLF | 10422 | 1475570061 | 1482316480 |
| 428 | 1:74910707 | Mightybastard | 7137 | 1475672897 | 1482209608 |
+-----+-------------+---------------+---------+--------------+-------------------+
4 rows in set (0.00 sec)
Now, how can I use INNER JOIN without doing like removing "STEAM_0:" or adding it. Also with explanation, please
You can join witn like operator, e.g.:
SELECT n.*, sp.*
FROM nmrihstats n JOIN store_players sp ON n.steam_id LIKE CONCAT('%', sp.authid);
Here's the SQL Fiddle.
Another approach would be to use String functions of MySQL to extract out relevant part from steam_id but I believe that's not what you want:
SELECT SUBSTR(steam_id, LOCATE('STEAM_0:', steam_id) + CHAR_LENGTH('STEAM_0:'))
FROM nmrihstats;
it is not possible, you need to remove "STEAM_0:", matching with WHERE, using substring for remove STEAM_0: from column equals to column in other table, or a new field into the T1 without "STEAM_0:", that 2 columns match for INNER JOIN

mysql, to get rows in tblA that aren't in tblB for an item in tblB

I'm trying to get a query to get the batchuuid from the batchTBL
that aren't in the JobBatchStatusTBL..
I've tried a couple of different queries trying to use something like:
select *
from BatchTBL as ba
left join JobBatchStatusTBL as j
on ba.BatchUUID=j.BatchUUID
join JobTBL as j2
on j.JobUUID=j2.JobUUID
where j.batchuuid IS NULL
and j.JobUUID = 'ecd0fab8-8bf1-83cc-b1d7-495034a55618';
but i'm screwing something up...
any thoughts?
thanks
mysql> select BatchName,BatchUUID from BatchTBL;
+-----------+--------------------------------------+
| BatchName | BatchUUID |
+-----------+--------------------------------------+
| aa | d288ff51-d045-d218-52fd-93e3523db85e |
| aa1 | a288ff51-d045-d218-52fd-93e3523db85e |
| aa3 | d188ff51-d045-d218-52fd-93e3523db85e |
| aaa3 | da88ff51-d045-d218-52fd-93e3523db85e |
| baa3 | db88ff51-d045-d218-52fd-93e3523db85e |
| z1 | 7eedfea4-c498-ed6e-f0dd-1397fe7dbd67 |
| d1 | 34781dba-d99c-82e3-f499-b55ded863f81 |
| nb | 1dd56d9c-daed-7f9f-c13b-246d2ec96513 |
| ds | cca9a771-b5ef-5926-4c26-21151215a800 |
| a1 | 1bb51584-e68a-21d1-a2df-e07707591b43 |
+-----------+--------------------------------------+
10 rows in set (0.00 sec)
mysql> select JobName,JobUUID from JobTBL;
+---------+--------------------------------------+
| JobName | JobUUID |
+---------+--------------------------------------+
| aa | 8afa9cf4-bf63-a4cd-3cd9-cbc6d17f84be |
| aa1 | ecd0fab8-8bf1-83cc-b1d7-495034a55618 |
+---------+--------------------------------------+
2 rows in set (0.00 sec)
mysql> select JobUUID,BatchUUID from JobBatchStatusTBL;
+--------------------------------------+--------------------------------------+
| JobUUID | BatchUUID |
+--------------------------------------+--------------------------------------+
| ecd0fab8-8bf1-83cc-b1d7-495034a55618 | d288ff51-d045-d218-52fd-93e3523db85e |
+--------------------------------------+--------------------------------------+
1 row in set (0.00 sec)
thanks
Your query puts an inner join on JobBatchStatusTbl to JobTbl, so rows that are in one but not the other will never be returned at all. You only need two of the tables for this:
SELECT *
FROM BatchTbl
WHERE JobUUID
NOT
IN (SELECT JobUUID
FROM JobBatchStatusTBL)
I should note that it's impossible to use the JobUUID in the WHERE clause as you're attempting in your initial query, because this is returning only batches for which there is no corresponding job, according to your post - which makes me wonder if your post was misworded, since you had a specific job uuid in your query?
On another note, you should never name tables, columns or anything else in a way that describes their schema type.
Try
select * from BatchTBL where JobUUID not in (select JobUUID from JobBatchStatusTBL)
If I understand what you are trying to do correctly. To "get a query to get the batchuuid from the batchTBL that aren't in the JobBatchStatusTBL"
use the not in SQL syntax. It is easier to write and read, and the optimizer will take care of the rest.
Select BatchName,BatchUUID from
BatchTBL where BatchUUID not in
(Select BatchUUID from JobBatchStatusTBL)