Regular expressions on strings in SQL statement - mysql

I have a table with following columns and sample data
File Name | Status
'xxx_2015-07-20.csv' | Completed
'xxx_2015-07-19.csv' | Completed
'xxx_2015-07-18.csv' | Failed
.
.
'xxx_2015-06-01.csv' | Failed
Now I have two scenarios in my application (PHP-MySQL):
1) I have to fetch the status of today's file. I can do it like this:
select status from myTable where file_name like '%date(Y-m-d)%';
2) I want to fetch the status of all files generated since 1 month from today. Suppose today is 2015-07-20, then files from 2015-06-20 should show up.
Since there is no date column, I can't apply comparison operator and get the results. I believe it will need some playing with regular expressions.
I am not familiar with regular expressions, so any help on this would be much appreciated.

If the pattern is same i.e. xxx_2015-07-20.csv you can use substring_index function to get the date value as
mysql> select substring_index(substring_index('xxx_2015-07-20.csv','_',-1),'.',1) as d;
+------------+
| d |
+------------+
| 2015-07-20 |
+------------+
Now using the same you can have the select statement as
select status from myTable
where
substring_index(
substring_index(file_name,'_',-1),
'.',1
) = curdate();

Related

Converting string extracted from json value to date returning NULL

I'm saving a date in one db field in json format. The json value looks like:
[{"key":"jkajdajsdiajsdik"},{"created_date":"2018-01-17 15:51:23"}]
I want to extract the created_date from json through sql and i'm getting it through the following query.
select SUBSTRING_INDEX(SUBSTRING_INDEX(testjson, 'created_date\":', -1),'}',1) as created_date from test
The above query returns
"2018-01-17 15:51:23"
Now I'm trying to convert this returned string to a date.
select STR_TO_DATE(SUBSTRING_INDEX(SUBSTRING_INDEX(testjson, 'created_date\":', -1),'}',1),'%Y-%m-%d %H:%i:%s') as created_date from test
But this is returning NULL. When I tried with a sample
SELECT STR_TO_DATE(" 2018-01-17 15:51:23",'%Y-%m-%d %H:%i:%s')
Its returning
2018-01-17 15:51:23
What am I doing wrong? Can anyone help me to fix this?
Thanks in advance
Your code is also including ". Make this small change to your code to exclude them:
select SUBSTRING_INDEX(SUBSTRING_INDEX(testjson, 'created_date":"', -1),'"}',1) as created_date from test
-- ^ ^
-- -------------------------------------------------------------+ |
-- ----------------------------------------------------------------------+
The date returned after Substring_Index() operations also contains double quotes. I added double quotes in the format specified for the Str_to_Date() function:
select STR_TO_DATE(
SUBSTRING_INDEX(
SUBSTRING_INDEX(testjson, 'created_date\":', -1),'}'
,1)
,'"%Y-%m-%d %H:%i:%s"')
AS created_date from test
Result
| created_date |
| ------------------- |
| 2018-01-17 15:51:23 |
View on DB Fiddle
However, in version 5.7 and above, it would be better to utilize JSON functions instead. We can use Json_Extract() function to get the value corresponding to created_date key, and the use the Str_To_Date() function.
Query #2
SET #j := '[{"key":"jkajdajsdiajsdik"},{"created_date":"2018-01-17 15:51:23"}]';
SELECT STR_TO_DATE(JSON_EXTRACT(#j, '$[*].created_date'), '["%Y-%m-%d %H:%i:%s"]') AS created_date;
Result
| created_date |
| ------------------- |
| 2018-01-17 15:51:23 |
View on DB Fiddle

Select a particular value of JSON string using MySQL

I have a table that looks like this
+------+------------------------------------+
| id | details |
+------+------------------------------------+
| 1 | {"price":"24.99","currency":"USD"} |
+------+------------------------------------+
Is it possible to, with a single MySQL select statement, obtain the value of price 24.99?
Yes, you can using JSON_EXTRACT
It probably should be like:
SELECT JSON_EXTRACT(details, "$.price")
FROM table_name
or another form:
SELECT details->"$.price"
FROM table_name
(I don't have MySql to test it)
Note that the price in your JSON stored as a string, not a number and you probably would want to cast it to a DECIMAL.

MySQL - GROUP_CONCAT if value is not a substring

I have a column called "Permissions" in my table. The permissions are strings which can be:
"r","w","x","rw","wx","rwx","xwr"
etc. Please note the order of characters in the string is not fixed. I want to GROUP_CONCAT() on the "Permissions" column of my table. However this causes very large strings.
Example: "r","wr","wx" group concatenated is "r,wr,wx" but should be "r,w,x" or "rwx". Using distinct() clause doesn't seem to help much. I am thinking that if I could check if a permission value is a substring of the other column then I should not concatenate it, but I don't seem to find a way to accomplish that.
Any column based approach using solely string functions would also be appreicated.
EDIT:
Here is some sample data:
+---------+
| perm |
+---------+
| r,x,x,r |
| x |
| w,rw |
| rw |
| rw |
| x |
| w |
| x,x,r |
| r,x |
+---------+
The concatenated result should be:
+---------+
| perm |
+---------+
| r,w,x |
+---------+
I don't have control over the source of data and would like not to create new tables ( because of restricted privileges and memory constraints). I am looking for a post-processing step that converts each column value to the desired format.
A good idea would be to first normalize your data.
You could, for example try this way (I assume your source table is named Files):
Create simple table called PermissionCodes with only column named Code (type of string).
Put r, w, and x as values into PermissionCodes (three rows total).
In a subquery join Files to PermissionCodes on a condition that Code exists as a substring in Permissions.
Perform your GROUP_CONCAT aggregation on the result of the subquery.
If it is a case here, that for the same logical entires in Files there exists multiple permission sets that overlaps (i.e. for some file there is a row with rw and another row with w) then you would limit your subquery to distinct combinations of Files' keys and Code.
Here's a fiddle to demonstrate the idea:
http://sqlfiddle.com/#!9/6685d6/4
You can try something like:
SELECT user_id, GROUP_CONCAT(DISTINCT perm)
FROM Permissions AS p
INNER JOIN (SELECT 'r' AS perm UNION ALL
SELECT 'w' UNION ALL
SELECT 'x') AS x
ON p.permission LIKE CONCAT('%', x.perm, '%')
GROUP BY user_id
You can include any additional permission code in the UNION ALL of the derived table used to JOIN with Permissions table.
Demo here

mysql - calculating difference between two times in query

I know I could use PHP to do this, but wanted to find out if there was a way to calculate the difference between two times using just a query? I tried the query below, but it's returning NULL for the time difference.
The data in my table is stored as:
| created | changed |
+------------+------------+
| 1333643004 | 1333643133 |
I wanted to figure out a way to return:
| 2012-04-05 09:23:24 | 2012-04-05 09:25:33 | 00:02:09 |
I tried:
SELECT
FROM_UNIXTIME(created) AS created,
FROM_UNIXTIME(changed) AS changed,
TIMEDIFF ( changed, created ) / 60 AS timediff
FROM content
WHERE id = 45;
Which yielded:
| 2012-04-05 09:23:24 | 2012-04-05 09:25:33 | NULL |
The result returned by TIMEDIFF() is limited to the range allowed for
TIME values. Alternatively, you can use either of the functions
TIMESTAMPDIFF() and UNIX_TIMESTAMP(), both of which return integers.
I would call UNIX_TIMESTAMP() on both columns (which returns integers) and then subtract them. This will give you an integer which you can convert in the query or in PHP.
SELECT
UNIX_TIMESTAMP(created) AS created,
UNIX_TIMESTAMP(changed) AS changed,
changed-created AS difference
FROM content
WHERE id = 45;
http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_unix-timestamp

Mysql-Select all tables from a database

I've a database called test and i've tables called x,y,z.
How do i select x,y,z and there is a column called date IN X,Y,Z check whether there is a particular date.
Is there any build in function that does this?
update
SELECT column date from all tables which is in a database called test
Thanks in advance!!
As far as I know, in SQL you cannot 'select a table', you can select some
column(s) from one or many tables at once. The result of such a query is an another table (temporary table) that you retrieve the data from.
Please be more specific about what exactly you want to do (e.g.: "I want to select a column 'z' from table 'tableA' and column 'y' from table 'tableB'") - then I'm sure your question has a pretty simple answer :)
SELECT x.date AS x_date, y.date AS y_date, z.date AS z_date FROM x,y,z;
That produces a result:
+---------+---------+---------+
| x_date | y_date | z_date |
+---------+---------+---------+
| | | |
| | | |
+---------+---------+---------+
Alternatively you can get everything in one column by ussuing a query:
SELECT date FROM x
UNION ALL
SELECT date FROM y
UNION ALL
SELECT date FROM z;
That produces a result:
+-------+
| date |
+-------+
| |
| |
+-------+
In the example above you would get also duplicate values in the single column. If you want to avoid duplicates replace 'UNION ALL' with 'UNION'
I'm still not sure if I undestood what you really want ot achieve, but I still hope that helps
Also take a look at:
http://www.w3schools.com/sql/sql_union.asp
http://www.sql-tutorial.net/SQL-JOIN.asp