How can I retrieve a text field from mysql db table, but not the entire text, just the few 40 or so characters.
Can this be done in sql or do I need to do it using php?
basically what I am trying to do is show the first x characters and then let the user click on that to view the full content.
SELECT LEFT(field, 40) AS excerpt FROM table(s) WHERE ...
See the LEFT() function.
As a rule of thumb, you should never do in PHP what MySQL can do for you. Think of it this way: You don't want to transmit anything more than strictly necessary from the DB to the requesting applications.
EDIT If you're going to use the entire data on the same page (i.e., with no intermediate request) more often than not, there's no reason not to fetch the full text at once. (See comments and Veger's answer.)
SELECT LEFT(MY_COLUMN, 40) FROM MY_TABLE
Function in the MySQL reference manual:
http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_left
try this... SELECT LEFT(field name, 40) FROM table name WHERE condition for first 40 and
SELECT RIGHT(field name, 40) FROM table name WHERE condition for last 40
You could do this in SQL as the others shown already.
But, if you also want to show the full text if the user clicks on it, you also need to full text and it seems a waste to let the database send you the short and the full text. So you could grab the full text and write some code to show the short text and the full text when the user clicks on it.
$result = mysql_query('SELECT text FROM table');
$row = mysql_fetch_row($result);
echo '<div onclick="alert(\''.$row[0].'\');">'.substr($row[0], 0, 40).'</div>';
Ofcourse you could do something nicer when you click on it (instead of alert()). Also you could do some PHP checking now to see if the original is shorter than 40 characters and handle situations like this.
Check this one as well,
mysql_query('SELECT LEFT('your text/fieldname', 40) FROM tablename');
Related
I have a database where I'm getting a random row from a table depending on a few variables. I'm trying to make it so it adds their username in this format (Admin, Jerry, Ben) once they view the advertisement (My project - clients view ads for Bitcoin). I want to make it so that once they view it , it adds their name in to a row called users_viewed_add (example is above). I need it to only get random rows based on if their username does not exist in the row users_viewed_add atoll so they can't view the ad more than once.
At the moment, I'm trying to do:
$query_second = mysqli_query($con, "SELECT * FROM business_advertisments WHERE ($users_credits >= amount_per_click) AND (users_viewed_add) NOT LIKE '$username' AND users_name != '$username' ORDER BY RAND() LIMIT 1");
As you can see, the AND (users_viewed_add) NOT LIKE '$username' is not working for me as it's reading the text as a whole word. The problem is that I'm using comma's to seperate the usernames of the clients who have viewed the ad. Is there any work around for this ? I know the method to check a block of text but it wouldn't work in a SQL statement I'm pretty sure.
You can do:
AND CONCAT(',', users_viewed_add, ',') NOT LIKE '%,$username,%'
But you probably want to make a separated many to many table, and use user id instead of user name.
If you want to use multiple values in your LIKE comparison, you can use:
AND users_viewed_add NOT LIKE ALL ('$username')
This will check that none of the $username values exists in the users_viewed_add field. You may need to format your variable properly so the SQL works.
I found the answer from this post: How do I add multiple "NOT LIKE '%?%' in the WHERE clause of sqlite3 in python code?
The correct SQL syntax to check a word doesn't exist in a row is:
AND users_viewed_add NOT REGEXP '[$username]'
EDIT: Ok, i found a way to get the cell-content and make a javascript variable (via dhtmlxgrid functions, something like var leadID = mygrid.cells(id,1).getValue();).
Now the remaining question is how i can get this javascript variable to be available in php for my sql query. On first pageload, since one of the table-cells should display the amount of comments made for this customer.
I need a query like (query is made on first pageload, to feed a cell with data)
$query_entryNo = mysql_query("select count(*) as total from comment WHERE post_id = $leadID ");
Where $leadID is the UserID you see in column 2 on screenshot.
End Edit
probably can ignore the text below...
Hello, i have something i dont know the answer and cannot find a way to do it.
Some info first:
I have an autogenerated table that is build with the help of dhtmlxgrid plugin (javascript). The table that is generated has no class or ID, also not the cells themself and i dont want to mess around with the plugin-sourcecode, for various reasons. So the table will stay class- and id-less.
Every row in this auto-generated table displays a user with his userID, name, email and all that.
I need to fetch this userid for an sql query. I would need this already on first pageload, not after some post or something like that. One column will contain the amount of comments that one made for this user and this i do with sql/php, soo i need some way to get the right db-entry. Comments are linked to the userid, thats why i need the id to be included in the php code for sql-query.
How can i achieve this? Basically the question is how i can get the id shown in column 2 into an sql query.
The screenshot shows the ID in the table that i somehow have to have in my sql query.
Since this table is generated through javascript and the comments are stored in another table i cannot use the basic dhtmlxgrid functions to do this. I have to build around my own way.
Based on our Discussion in the comments I can give you this Solution:
Send Data from PHP to Javasript (at Site-Creation time on Server side): just add a echo "<script>var data=$data; </script>", if it is more complicated you have to convert it into JSON (google that).
To send data on-the fly from Javascript to PHP you need a PHP-side recieving page, that reads your POST-Data. To send the request just use jquery.post like this:
$.post("http://example.com/ajax.php", data);
This will send an asynchronous call to your server.
So in your case, you read the values from the table via Javascript, save them into an array, and prepare the data that it will be interpreted the right way by PHP-Post mechanism:
ajaxData = "";
for (int i = 0; i < tableData.length; i++) {
ajaxData += "data[" + i + "]=" + tableData[i] + "&";
}
$.post("ajax.php", data); //This will take the relative path to your site
You see, that POST data has to be encoded the same way as GET-data.
Hope I could help.
I have a database with almost 100,000 comments and I would like to detect the most used words (using stop words to avoid common words).
I want to do this only one time, and then use a few of the most popular words to Tag the comments that contains them.
Can you help me with the Query and PHP code to do this?
Thanks!
The easiest approach I guess would be:
Create two new tables: keywords (id, word) and keywords_comments (keyword_id, comment_id, count)
keywords saves an unique id and the keyword you found in a text
keywords_comments stores one row for each connection between each comment that contains that keyword. In count you wil save the number of times this keyword occurred in the comment. The two columns keyword_id + comment_id together form a unique or directly the primary key.
Retrieve all comments from the database
Parse through all comments and split by non-characters (or other boundaries)
Write these entries to your tables
Example
You have the following two comments:
Hello, how are you?!
Wow, hello. My name is Stefan.
Now you would iterate over both of them and split them by non-characters. This would result in the following lowercase words for each text:
- First text: hello, how, are, you
- Second text: wow, hello, my, name, is, stefan
As soon as you have parsed one of this text, you can already insert it into the database again. I guess you do not want to load 100.000 comments to RAM.
So it would go this:
Parse first text an get the keywords above
Write each keyword into the tabke keywords if it is not there yet
Set a reference from the keyword to the comment (keywords_comments) and set the count correctly (in our example each word occurs only once in each text, you have to count that).
Parse second text
…
Minor improvement
A very easy improvement you probably have to use for 100.000 comments, is to use a counting variable or add a new field has_been_analyzed to each comment. Then you can read them comment by comment from the database.
I usually use counting variables when I read data chunkwise and know that the data cannot not change from the direction I am starting (i.e. it will stay consistent up to the point I currently am). Then I do something like:
SELECT * FROM table ORDER BY created ASC LIMIT 0, 100
SELECT * FROM table ORDER BY created ASC LIMIT 100, 100
SELECT * FROM table ORDER BY created ASC LIMIT 200, 100
…
Consider that this only works if we know for sure that there are no dates to be added at a place we think we already read. E.g. using DESC would not work, as there could be data inserted. Then the whole offset would break and we would read one article twice and never read the new article.
If you cannot make sure that the outside counting variable stays consistent, you can add a new field analyzed which you set to true as soon as you have read the comment. Then you can always see which comments have already been read and which not. An SQL query would then look like this:
SELECT * FROM table WHERE analyzed = 0 LIMIT 100 /* Reading chunks of 100 */
This works as long as you do not parallelize the workload (with multiple clients or threads). Otherwise you would have to make sure that reading + setting true is atomar (synchronized).
In my web application there will be several users. and they have their own contents uploaded to my webapp. For each content they upload it has a title, description and tags(keywords). I can write a search script to search for content or user name. but they keywords when they have given with a spelling mistake it doesn't return any result. For example if there is a user named "Michael" in the database and the search query was "Micheal" i should get "Did you mean to search for 'Michael'" which is none other than a search suggestion.
Also this suggestion should be for the contents uploaded by the user. An user may keep their content's title as "Michael's activities May 2011" and suggestions should be generated for individual words.
You could use SOUNDEX to search for similar-sounding names, like that:
SELECT * FROM users WHERE SOUNDEX(name) = SOUNDEX(:input)
or like that
SELECT * FROM users WHERE name SOUNDS_LIKE :input
(which is completely equivalent)
Edit: if you need to use an algorithm other than Soundex, as Martin Hohenberg suggested, you would need to add an extra column to your table, called, for example, sound_equivalent. (This is actually a more efficient solution as this column can be indexed). The request would then be:
SELECT * FROM users WHERE sound_equivalent = :input_sound_equivalent
The content of the sound_equivalent column can then be generated with a PHP algorithm, and inserted in the table with the rest of user parameters.
You can also use the php library pspell to get suggestions if you have no search results.
Maybe create a database of the most common words (like: dog, house, city, numbers, water, internet). Don't need to make it big (<10000 words).
Then when you explode the search term, check the "word" database for words LIKE the search terms. Then just echo out the suggestions.
Suppose it is a long article (say 100,000 words), and I need to write a PHP file to display page 1, 2, or page 38 of the article, by
display.php?page=38
but the number of words for each page can change over time (for example, right now if it is 500 words per page, but next month, we can change it to 300 words per page easily). What is a good way to divide the long article and store into the database?
P.S. The design may be further complicated if we want to display 500 words but include whole paragraphs. That is, if we are showing word 480 already but the paragraph has 100 more words remaining, then show those 100 words anyway even though it exceeds the 500 words limit. (and then, the next page shouldn't show those 100 words again).
I would do it by splitting articles on chuks when saving them. The save script would split the article using whatever rules you design into it and save each chunk into a table like this:
CREATE TABLE article_chunks (
article_id int not null,
chunk_no int not null,
body text
}
Then, when you load a page of an article:
$sql = "select body from article_chunks where article_id = "
.$article_id." and chunk_no=".$page;
Whenever you want to change the logic of splitting articles into pages, you run a script thats pulls all the chunks together and re-splits them:
UPDPATE: Giving the advice I suppose your application is read-intensive more than write-intensive, meaning that articles are read more often than they are written
You could of course output exactly 500 words per page, but the better way would be to put some kind of breaks into your article (end of sentence, end of paragraph). Put these at places where a break would be good. This way your pages won't have exactly X words in it each, but about or up to X and it won't tear sentences or paragraphs apart.
Of course, when displaying the pages, don't display these break markers.
You might want to start by breaking the article up into an array of paragraphs by using split command:
http://www.php.net/split
$array = split("\n",$articleText);
It's better way to manually cut the text, because it's not a good idea to leave a program that determines where to cut. Sometimes it will be cut just after h2 tag and continue with text on next page.
This is simple database structure for that:
article(id, title, time, ...)
article_body(id, article_id, page, body, ...)
The SQL query:
SELECT a.*, ab.body, ab.page
FROM article a
INNER JOIN article_body ab
ON ab.article_id = a.id
WHERE a.id = $aricle_id AND ab.page= $page
LIMIT 1;
In application you can use jQuery to simple add new textarea for another page...
Your table could be something like
CREATE TABLE ArticleText (
INTEGER artId,
INTEGER wordNum,
INTEGER wordId,
PRIMARY KEY (artId, wordNum),
FOREIGN KEY (artId) REFERENCES Articles,
FOREIGN KEY (wordId) REFERENCES Words
)
this of course may be very space-expensive, or slow, etc, but you'll need some measurements to determine that (as so much depends on your DB engine). BTW, I hope it's clear that the Articles table is simply a table with metadata on articles keyed by artId, and the Words table a table of all words in every article keyed by wordId (trying to save some space there by identifying already-known words when an article is entered, if that's feasible...). One special word must be the "end of paragraph" marker, easily identifiable as such and distinct from every real word.
If you do structure your data like this you gain lots of flexibility in retrieving by page, and page length can be changed in a snap, even query by query if you wish. To get a page:
SELECT wordText
FROM Articles
JOIN ArticleText USING (artID)
JOIN Words USING (wordID)
WHERE wordNum BETWEEN (#pagenum-1)*#pagelength AND #pagenum * #pagelength + #extras
AND Articles.artID = #articleid
parameters #pagenum, #pagelength, #extras, #articleid are to be inserted in the prepared query at query time (use whatever syntax your DB and language like, such as :extras or numbered parameters or whatever).
So we get #extras words beyond expected end-of-page and then on the client side we check those extra words to make sure one of them is the end-paragraph marker - otherwise we'll do another query (with different BETWEEN values) to get yet more.
Far from ideal, but, given all the issues you've highlighted, worth considering. If you can count on the page length always being e.g. a multiple of 100, you can adopt a slight variation of this based on 100-word chunks (and no Words table, just text stored directly per row).
Let the author divide the article into parts themselves.
Writers know how to make an article interesting and readable by dividing it into logical parts, like "Part 1—Installation", "Part 2—Configuration" etc. Having an algorithm do it is a bad decision, imho.
Chopping an article in the wrong place just makes the reader annoyed. Don't do it.
my 2¢
/0