SQL - How to get certain characters from a column? - mysql

I have a table as:
id: Int,
URL: string,
//other fields
The URL field contains values like ["nytimes.com/live/", "prisma.io/docs/reference/api-reference/", "stackoverflow.com/questions",...]
How do I query to only get the domains of URLs ["nytimes.com", "prisma.io", "stackoverflow.com"...]
Right now I am doing it by fetching all the records and capturing the domain in server. I was wondering if there is a way to do this in SQL directly?

SELECT SUBSTRING_INDEX(URL, '/', 1) FROM table ;

In SQL Server,
CHARINDEX returns the position of a given character.
SUBSTRING returns the substring from the start of the string until the given index
Hence, combining CHARINDEX and SUBSTRING function, we can get the domain name.
Eg, if the domain name is google.com, the following query will return 'google'
SELECT SUBSTRING(URL, 1, CHARINDEX('.',URL)) FROM table_name
The solution for mysql database given by #ricardo-francois works just as intended.
CREATE TABLE domains (id int auto_increment primary key, url varchar(100) not null);
INSERT INTO domains(url) values('nytimes.com/live/'),('google.com/crawl');
SELECT SUBSTRING_INDEX(URL, "/",1) FROM table_name;
The last parameter 1 in the SUBSTRING function indicates the number of occurrences of the delimiter. Here, it will return all the texts until the first delimiter (which is "/")
Output :
nytimes.com
google.com

Related

Oracle reading JSON data using json_query

While working on oracle json datatype and trying to extract data from it, not able to extract name & value elements from this. tried using all known notations but getting null.
select json_query(po_document, '$.actions.parameters[0]') from j_purchaseorder where ID='2';
You can use the JSON_VALUE function as follows:
SQL> select JSON_VALUE('{"_class":"123", "name":"tejash","value":"so"}', '$.name') as name,
2 JSON_VALUE('{"_class":"123", "name":"tejash","value":"so"}', '$.value') as value
3 from dual;
NAME VALUE
---------- ----------
tejash so
SQL>
Thanks for your help. got required output using below
select json_value(json_query(po_document, '$.actions.parameters[0]'),'$.value') from j_purchaseorder where ID='2' and
json_value(json_query(po_document, '$.actions.parameters[0]'),'$.name') = 'SERVERUSER';
As explained, for example, in the Oracle documentation, multiple calls to JSON_VALUE() on the same JSON document may result in very poor performance. When we need to extract multiple values from a single document, it is often best (for performance) to make a single call to JSON_TABLE().
Here is how that would work on the provided document. First I create and populate the table, then I show the query and the output. Note the handling of column (attribute) "_class", both in the JSON document and in the SQL SELECT statement. In both cases the name must be enclosed in double-quotes, because it begins with an underscore.
create table j_purchaseorder (
id number primary key,
po_document clob check (po_document is json)
);
insert into j_purchaseorder (id, po_document) values (
2, '{"_class":"hudson.model.StringParameterValue","name":"SERVERUSER","value":"avlipwcnp04"}'
);
commit;
select "_CLASS", name, value
from j_purchaseorder
cross apply
json_table(po_document, '$'
columns (
"_CLASS" varchar2(40) path '$."_class"',
name varchar2(20) path '$.name',
value varchar2(20) path '$.value'
)
)
where id = 2
;
_CLASS NAME VALUE
---------------------------------------- ------------------ ------------------
hudson.model.StringParameterValue SERVERUSER avlipwcnp04

How to check if exact slug (either single occurence or multiple occurence) is present in a Mysql DB?

I am creating new slug. Say my slug variable is $slug = 'About-Us'.
I have a table where there is a field called slug. The values of slug column can be like this:-
'About-Us'
'About-Us-2',
'About-Us-3',
'About-Us-5'
In case of duplicate slugs, we are appending a numeric value after the last dash.
'About-Us-2',
'About-Us-3',
'About-Us-5'
When inserting new data, we need to check if a slug is either present in exact form, or the part followed by the last "-" dash is a numeric one.
I wanted to check this by using this query
"SELECT COUNT(*) FROM table WHERE SLUG LIKE 'About-Us%'"
The above query has a problem. If a slug is present like "About-Uses", then it is returning a count 1. What we need to check is whether the section after the last dash is numeric or not.
Also slugs like "About-Us-2-Know" must be considered different from 'About-Us', while 'About-Us-2' or 'About-us-3' must be considered as multiple occurence of 'About-Us'
EDIT:
This is not duplicate. It is not about only checking with last character as numeric. It is about checking whether the string before last dash is exact match and string after last dash is a numeric.
Here is how I solved using only MySql. May need to tweak for your needs, but using SUBSTRING_INDEX is the main solution for me.
/*
'About-Us'
'About-Us-2',
'About-Us-3',
'About-Us-5'
*/
DROP TABLE IF EXISTS `bleach`;
DROP TABLE IF EXISTS `bleach2`;
CREATE TABLE bleach (slug VARCHAR (255) NOT NULL);
INSERT INTO bleach SELECT 'About-Us';
INSERT INTO bleach SELECT 'About-Us-2';
INSERT INTO bleach SELECT 'About-Us-3';
INSERT INTO bleach SELECT 'About-Us-5';
INSERT INTO bleach SELECT 'About-Us-6-extra';
INSERT INTO bleach SELECT 'About-Us-NoMatch';
-- About us match
CREATE TABLE bleach2
SELECT slug, SUBSTRING_INDEX(slug,'-',2) AS about_us,
SUBSTRING_INDEX(slug,'-',-1) AS first_numeric,
SUBSTRING_INDEX(SUBSTRING_INDEX(slug,'-',-2),'-',1) AS second_numeric
FROM bleach;
SELECT * FROM bleach2;
-- All but About-Us-NoMatch should return
SELECT * FROM bleach2 WHERE about_us='About-Us' AND
(first_numeric IN ('1','2','3','4','5','6','7','8','9') OR second_numeric IN ('1','2','3','4','5','6','7','8','9'))
OR second_numeric='About';

MySQL regular expression to select the last integer in the string

I have a MySQL database table that contains column run that is an integer and another column filename that is a varchar with typical values like RUN0001.FTS or 3DS0231.FTS or 3RUN0010.FTS
I need to check the values in the run and filename columns. The prescription is I extract the last integer (without leading zeroes) before the dot character (.) in the filename column, and compare it to the value of the run column. How do I write a select statement to do this comparison to return the rows that will not have the matching integers?
For example, a regular expression I am trying to build would extract 1 from RUN0001.FTS, or 231 from 3DS0231.FTS, or 10 from 3RUN0010.FTS and then compare it to the value in the run column, and return the primary key if the two don't match.
In Python I would manipulate the variable filename = '3RUN0010.FTS' like so:
import re
filename = '3RUN0010.FTS'
fileRunNumber = re.findall('\d+', filename)
runNumber = int(fileRunNumber[-1])
print "The integer I want is", runNumber
How do I do this in as a MySQL statement?
Thanks,
Aina.
You can try the following query:
SELECT CAST(SUBSTRING(col, INSTR(col, '.') - 4, 4) AS UNSIGNED) AS theNumber
FROM yourTable
Data:
CREATE TABLE yourTable (col varchar(55));
INSERT INTO yourTable (col)
VALUES
('RUN0001.FTS'),
('3DS0231.FTS'),
('3RUN0010.FTS');
Output:
Demo here:
Rextester

getting data directly from insert query after running it

i have a database i insert item into using php. i want to get the ID which is auto increment column, i read the manual and it says that the mysql_query returns a resource variable rather than boolean, is there any way to retreive data from that resouce?
echo $query_ins = "INSERT INTO `house` VALUES ('' , '$city', '$street', 'num');
$res = mysql_query($query_ins);
the first field is the ID field i am interested in.
i tried mysql_fetch_assoc and mysql_result function to convert the $res into array or retrieve data directly like i would do with SELECT query but no succes.
any suggestions?
See the manual: mysql_insert_id — Get the ID generated in the last query
This is really something you should have been able to find on your own easily, without posting to StackOverflow. It's to your advantage to review the documentation of any API you're using.
Re your comment:
SELECT * FROM house WHERE id = LAST_INSERT_ID()
This supposes you have an auto-incrementing primary key.
If you generate a nondeterministic primary key value on insert, for example using RAND() or UUID(), then there is effectively no way to retrieve the value generated. You should generate the value before doing the INSERT, so you have a literal value you can use to look up the row.
SET #r := RAND();
INSERT INTO house (id, ...) VALUES (#r, ...);
SELECT * FROM house WHERE id = #r;
MD5 is deterministic, so supposing you have an original key string that you hash, you should be able to retrieve the row using that MD5 expression and the original string.
INSERT INTO house (id, ...) VALUES (MD5('xyzzy'), ...);
SELECT * FROM house WHERE id = MD5('xyzzy');

How to handle mysql #1062 - Duplicate entry error when creating a large table

I am working on a table having around 5 million records. I'm loading records from a csv file.
There is a unique column, url.
While inserting, if the url is already in the table, I want to make a change in the new url value and then do the insertion.
Example:
try inserting a record with a url of "book". If "book" already exists, the new record should have a url of "book-1" (then "book-2" and so on)
result: the url values "book-1","book-2"... are in the table in addition to the initial value book
I have figured out that there are 2 ways to do so.
before inserting each record: check whether the url value already exists; if it does then make the required changes in the new url value and insert. I am afraid that this will result in a poor performance.
insert records without checking if the url value already exists. If url value already exists handle the "mysql #1062 - Duplicate entry error" and make the required changes in the url value; retry the insertion.
Is this possible? If so, how?
If this is an one-off problem, I'd like to recommend an ad-hoc MySQL solution:
If your table isn't MyISAM, convert to MyISAM.
Temporarily create an auto_increment integer column named
url_suffix.
Temporarily delete the unique constraint on the url column.
Create the multiple-column index (url, url_suffix) and ensure that there are no other indexes that use url_suffix.
Insert all of your rows, allowing duplicate URLs. You'll notice that the auto_increment url_suffix column is keyed on the url now. So, the first particular url will have url_suffix of 1 and the next 2, and so on.
Do an update like the following, then delete your temporary url_suffix column and put your unique constraint back.
Query to update all the rows:
UPDATE urls
SET url = if (url_suffix = 1, url, CONCAT(url, '-', url_suffix - 1))
In fact, you could skip step 6, keep the auto_increment field so you could easily add duplicate URLs in the future, and simply fetch your URLs like this:
SELECT (if (url_suffix = 1, url, CONCAT(url, '-', url_suffix - 1))) AS url
FROM urls
Your data would look something like this:
url url_suffix
---------------------------
that 1
that 2
this 1
this 2
this 3
those 1
You have the problem here that a simple trigger will prove inefficient when inserting due to the fact that you are saying they will go from 'book' to 'book-1' 'book-2' etc. The easiest way to do this would be to have a new column which contains a numeric value defaulting to 0. This could be done in a stored procedure i.e.
CREATE PROCEDURE `insertURL`(inURL VARCHAR(255))
BEGIN
DECLARE thisSuffix INT UNSIGNED DEFAULT 0;
// We have to get this ID first, as MySQL won't let you select from the table you are inserting to
SELECT COALESCE(MAX(url_suffix)+1,0) INTO thisSuffix FROM urls WHERE url_column = inURL;
// Now the ID is retrieved, insert
INSERT INTO urls (
url_column,
url_suffix
) VALUES (
inURL,
thisSuffix
);
// And then select the generated URL
SELECT IF(thisSuffix>0,CONCAT(inURL,'-',thisSuffix),inURL) AS outURL;
END
Which is then invoked using
CALL insertURL('book');
And will then return 'book' if the suffix = 0, or 'book-1' if it's got a suffix greater than 0.
For purposes of testing my table design was
CREATE TABLE `urls` (
`url_column` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
`url_suffix` tinyint(3) UNSIGNED NOT NULL ,
PRIMARY KEY (`url_column`, `url_suffix`)
);