How to refference a value from the same row in mysql? - mysql

I am retrieving a long text blurb for a row. Example: a description for a book. Is there a way that I can reference other values of the same row in the longer text as a form of variable. The idea here being that I don't have to comb through the entire long text output and change every instance of the value where referenced.
Using the same as before: a description which is a column retrieved from the same row as say the title and author of the same book:
"$TITLE is a book written by $AUTHOR etc. etc."
If for example the same row had a title column and author column with the value of "Huckleberry Fin" and "Mark Twain" and a description column with the value of "$TITLE is a book written by $AUTHOR etc. etc."" .. When the description was retrieved, the description would read "Huckleberry Fin is a book written by Mark Twain etc. etc."
Re-Using the same example:
If the above row's title were updated to "The Adventures of Huckleberry Finn" without updating the description, which would be a laborious and tedious process that I would like to avoid, when the description is retrieved it would read: "The Adventures of Huckleberry Finn is a book written by Mark Twain"
Maybe this doesn't exist and I would have to make my own engine for it web server side, but it seems like the best option for efficiency would be to have this done in the database and not the web server. Maybe I don't know enough about MySQL to know that this could be achieved using something like a view for instance. Anyway, it seems like this would be a very common thing to have done on the server and I can't imagine that this cannot be done... but then again, maybe I am missing something really simple.

You could use REPLACE:
SELECT title, REPLACE(description, '$TITLE', title) as description FROM books
But it's going to be ureadable if you need to replace multiple placeholders using nested REPLACE expressions:
SELECT title,
REPLACE(
REPLACE(description, '$TITLE', title),
'$MAINCHARACTER',
main_character
) as description
FROM books
I would rather do it in application language. For example with PHP you could use:
$description = str_replace(
['$TITLE', '$MAINCHARACTER'],
[$title, $mainCharacter],
$description
);
Adding more placeholders wouldn't make it unreadable.
[..] but it seems like the best option for efficiency would be to have
this done in the database and not the web server.
I don't see any reason, why any language should do that less efficient than MySQL.
Anyway, it seems like this would be a very common thing to have done
on the server
I doubt that. You will find a lot of comments like "Why don't you do that in application language?". At least MySQL has a very limited support for string manipulation.

Are you trying to call different data within the same row? You can use mysql_fetch_row.
If yes, you can add a column of index, like
=============================
index |title |character
1 | Huckleberry Fin | Tom Sawer
2 | ABC | John
==============================
And say you have your table name called "books", Then you do
$handle = mysql_query('SELECT * FROM books WHERE index=1');
$row = mysql_fetch_row($handle);
so $row[0]=1, $row[1]=Huckleberry Fin, and $row[2]=Tom Sawer
You can take a look at this manual.
And you may want to learn how to use escape functions like mysql_escape_string()here.
P.S. Sorry for the ugly table drawn LOL

Related

Fetch subtitle lines (English and Chinese) from a video table of a server database

First of all, my knowledge on database is limited.
I have a video table (in a server database) with a subtitle_content column which is medium text type of English and Chinese. Here is a sample text of the column in the video table , which is actually srt subtitle (Note: the Chinese sentence is the translation of the preceding English. The number of rows of the video table would be something like ten to fifteen thousands, and the column of each row would contains about a hundred lines of text like below.):
1
00:00:02,000 --> 00:00:04,330
13 meters. You should see it.
13米 您应该看到它。
2
00:00:17,682 --> 00:00:19,392
Okay, take her up and over the bow rail.
好吧,将她抬起并越过弓杆。
3
00:00:21,853 --> 00:00:25,193
Mir 2, we're going over the bow. Stay with us.
米尔2,我们过去了。 和我们在一起。
4
00:00:59,224 --> 00:01:01,394
Okay, quiet. We're rolling.
好的,安静 我们正在滚动。
5
00:01:01,851 --> 00:01:05,181
Seeing her coming out of the darkness like a ghost ship...
看到她像幽灵船一样从黑暗中出来...
There is a similar question here
php laravel regex query for fetching a part of subtitle from database server, while my situation is different in that there are two languages in the subtitle_content column of the video table, and the timestamps of the subtitle lines are not needed to return in the search, they are retrieved in other API for video playing.
What I want to implement is to search an English word or phrase, and the database would return the English sentence with this searching parameter, as well as the following Chinese sentence. While if the searching parameter is Chinese, the Chinese sentence with the searching parameter would be returned, with the preceding English sentence.
My questions regarding the design of the database are:
Would full text index be applied for the search for optimization, and how for this bilingual situation? (Answer in the similar question doesn't mention this technique.)
Would dividing the subtitle_content into English and Chinese and storing them in two columns (each for one language search, full text index would be easily implemented) sound like a direction towards a better solution? But the problem I can think of lies in two ways: first, the expense of creating another column; second, when a match of search is found in one language in one column, getting the corresponding Chinese or English in another column is also an expense.
Is mysql is the type of database to get the job done here, or is there a better choice of database?
Your help is greatly appreciated.
you can use the same query.
you have 4 columns in your table (id, timeslot ,text_english. text_chinese), and you select the columns you want with the search pattern
text_english Like '%rolling%"
you can also take a look at FULLTEXTINDEXo
Which would allow you to seartch morre complex word phrasing, or even give you an estimate, how gopd it fits.
Schema
Schema::create('subtitle', function (Blueprint $table) {
$table->increments('id');
$table->string('time_duration');
$table->string('text_english');
$table->string('text_chinese');
});
$faker = \Faker\Factory::create();
CODE
$faker = \Faker\Factory::create();
DB::insert('insert into subtitle (time_duration, text_english, text_chinese)
values (?,?,?)', [ "00:00:02,000 --> 00:00:04,330", "13 meters. You should see it.", "13米 您应该看到它。"]);
$users = DB::table('subtitle')
->where('text_english', 'LIKE', '%should%')
->orWhere('text_chinese', 'LIKE', '%should%')
->first();
return $users;
you can run this here https://implode.io/j14COO

Matching strings without space and punctuation in MySQL

I'm working on a query which I thought should be quite intuitive, but somehow I'm facing a bit of issues when implementing it. I guess what I'm trying to achieve is to match a string stored in MySQL DB without space and punctuation (other creative approaches are more than welcome). At the same time I would like the query to handle Unicode characters in diacritics insensitive fashion (so options like REGEXP are kinda out of luck). And the last condition is I'm on MySQL 5.5 with InnoDB engine, so full-text indexing is not supported (but I'm open to upgrade to 5.6/5.7 if it helps sorting this out).
Consider the scenario which the string Hello-World from John Doe is stored in DB. I would like to find it when given the search string HelloWorld or JohnDoe. To be more general, the string in DB can contain brackets, understores and any other punctuation (not limited to ASCII but can compromise for now), while the search string can be a combination of words with or without any separators in between. The closest I've gotten so far is to daisy chain the REPLACE function for a list of known punctuation, like below:
SELECT text FROM table WHERE REPLACE(REPLACE(text, '-', ''), ' ', '') LIKE '%JohnDoe%'
My questions are:
Is there a better way instead of using the daisy chain above?
If that's the only solution, how will the performance be impacted when I chain up hundred or more REPLACE functions?
Thanks in advance for your help.
I don't know how restrictive your searches must be, but you could try to strip out all non-alphanumeric characters from it, so that you end up with a string like "HelloWorldfromJohnDoe" that you match with instead.
Have a look at this answer: How to remove all non-alpha numeric characters from a string?
You might have to change it around a bit though to make it fir your purposes. I changed it from CHAR(32) to CHAR(255) to make sure I could get the column, but you might want to look into changing the function altogether to fit your data more precisely.
Then you something like this:
SELECT *
FROM testing
WHERE alphanum(test) LIKE CONCAT('%', alphanum('John Doe'), '%')
which should give you a hit.
Method 1
I would have another column on the schema containing an "hashed" version of the name, for example, let's say you have the user:
John Doe The Great
This name hashes to
johndoethegreat
The hash function is coded in such a way that all of the following strings:
John_Doe_THE_great
John Doe The GREAT
John.Doe.The.Great
johnDOE___theGreat
john Doe the great
___john____DOE____THE____great
hash to the same value
johndoethegreat
It's trivial to write such a function. This way you can get the user input, hash it and then compare it against the hash column in your database
Names like:
Jon Doe
John Doo
will not be found of course
Method 2
Use the FULLTEXT search feature built-in in MySQL, sort the results by score and pick the first non zero entry
http://blog.oneiroi.co.uk/mysql/php/mysql-full-text-search-with-percentage-scoring/
I am totally missing the point of your question. You appear to have the string:
Hello-World from John Doe
If you want to find this when the search string is JohnDoe or John Doe, then you only need to substitute spaces:
where replace(text, ' ') like concat('%', 'JohnDoe', '%')
If you want a string that contains both "John" and "Doe" in that order, then:
where replace(text, ' ') like concat('%', 'John%Doe', '%')
I fail to see why 100 nested replace()s would be needed.

Use REGEXP in MySQL to match keywords for search engine in random order

I'm trying to use a regular expression to match a user entered search string to a title of an entry in my MySQL database.
For example I have the following rows in a table in my databse:
id title
1 IM2 - Article 3 Funky Business
2 IM2 - Article 4 There's no Business That's not Show Business
3 IM2 - There's no Business That's not Show Business
4 CO4 - Life's a business
When a user searches for "IM Article Business", the following query will be executed (spaces are replaced by "(.*)" using str_replace):
SELECT * FROM mytable WHERE title REGEXP 'IM(.*)Article(.*)Business'
This will return the first 2 rows.
Now, I want it to show the same results when a user uses the same words, but in another order, for example: "Business IM Article". The results MUST contain all words entered, only the order of how the words are entered shouldn't matter.
I couldn't figure out how to do it in any way and hoped regular expressions would be the answer. I've never used them before, so does anybody know how to do this?
Thanks,
Pascal
This isn't something regular expressions are great at. Fortunately, it's something SQL is pretty good at. (I'm going to not use mysql's regexp keyword, which I didn't even knew existed, and instead use the SQL standard "%" glob matching.)
select * from mytable where title like '%IM%' and title like '%Article%' and title like '%Business%'
Now title has to contain all three strings, but you haven't specified an order. Exactly what you want.

Alphabetically ordering records with "The", "A", "An" etc at the beginning of varchar field

I'm looking for both MySQL and PostgreSQL solutions for this kind of problem.
Say I have a number of records with a title field. The titles are book or movie titles, like "The Cat in the Hat" and "Robin Hood". But while the titles must be displayed in their original form, they ought to be sorted in the way that libraries sort them, which is by moving any article, like "The" or "An" to the end of the title.
So "The Cat in the Hat" is sorted as if it were "Cat in the Hat, The".
What's the best way either to design the schema or write the query so that these records are sorted by title in the same way that libraries sort the title? (I also wish I knew the technical term for this type of ordering by title.) Also, what performance considerations should I be aware of and what indexes should I create?
Why don't you just add a "title_prefix" field to the table and move all these "the" and "a" strings there? When you're ordering you would use the "title" field, and when you are presenting the title you could do the concatenation in any way you wish.
Create a custom function that (sortableTitle, perhaps?) that will modify strings starting with your unwanted words. Finish your query statement with order by sortableTitle(title). This will incur an extra CPU cost, though you'll have to benchmark to know how much so.
You could create an extra column (sortTitle) that is populated by a trigger. This will take up some space, but then your server will be able to sort rows by an index.
Excepting the above, you cannot (without modifying the database server code) directly create an index that is in the order you want. As far as I can tell, that applies to both MySQL and PostgreSQL.
iTunes achieves this by having a second field in which the title is stored in the desired sorting format and sorting on this instead of title. It does sound like the cheap way out, but when you consider the performance implications of doing string manipulations on every title every time you do a select statement that orders by title, against doing string manipulations each time you insert or update the title, it does make sense.
Select * from TitleTable
Order by
Case when substring(title,0,4) = 'The ' then substring(title, 4, len(title)-4)
when substring(title,0,3) = 'An ' then substring(title, 3, len(title)-3)
when substring(title,0,2) = 'A ' then substring(title, 2, len(title)-2)
else title
end
I would suggest you split the title field in two fields: mainTitle and pre.
When a title is added, check if it starts with "A", "The" or other prefixes and split it (perhaps with a trigger) into the two fields. Your table would look like this:
| pre | mainTitle |
|-----|----------------|
| The | Cat in the Hat |
| A | Space Odyssey |
| | Eyes Wide Shut |
So, you can have an index on the mainTitle field and use it for sorting.
When you want to show the full title, concat the two fields, in either of the two forms.
If you choose this way, you'll have to modify accordingly the code for when a user gives a title to search in your table. The given title will have to be split the same way before searching the mainTitle field.
You'll have to be very, very careful with the code (trigger or other) that does the spliting so some special cases are caught correctly. You wouldn't want to have the A = B or the A B C: learn the alphabet books shown and sorted as = B, A and B C: learn the alphabet, A

How to do full text search similar to "like '%search%' in SQL Server 2008

We are trying to filter out some suspicious bogus fields in our database. And I think full text search is the way to go after I read some posts. However I found full text search does not work the way I expected. For example.
SELECT name FROM dbo.Account WHERE contains(Name, '"n/a"')
does not return anything
SELECT name FROM dbo.Account WHERE Name like '%n/a%'
returns two records
Name
Applimation, Inc. - N/A
n/a
Any idea how to make it work?
thanks
I don't have the reference handy, but the SQL Server fulltext engine does not index words that are too short (noise words) such as "a", "or". It could possibly also include "n/a".
Another possibility is that the '/' is a word breaker in your particular language setup
http://msdn.microsoft.com/en-us/library/ms142509.aspx
Or you can check the fts stop list for a short phrase containing n/a to see if it will be indexed.
http://msdn.microsoft.com/en-us/library/cc280463.aspx