Not sure if it's possible to do this in SQL but... I'm having difficulty selecting results between certain criteria. I have a column that is a mixture of text and numeric. For example: LOC:05-04-01. I'm wanting to select items between two locations. EG: between LOC:05-04-01 and LOC:05-04-20.
I've tried using the standard BETWEEN statement but it returns an empty result.
$loc1 = 'LOC:05-04-01';
$loc2 = 'LOC:05-04-20';
$sql = $dbh->prepare("SELECT * FROM table WHERE location BETWEEN ? AND ? ORDER BY location DESC");
$sql->execute([$loc1,$loc2]);
while ($row = $sql->fetch(PDO::FETCH_ASSOC)) {
echo $row['ID'].': '.$row['location'].'<br>';
}
My database is similar to below:
ID | Location
1 | LOC:05-04-01
2 | LOC:05-04-02
3 | LOC:05-04-05
4 | LOC:06-04-01
5 | LOC:06-04-02
6 | LOC:06-04-10
I'm expecting to see a list of locations out of the above query such as:
1: LOC:05-04-01
2: LOC:05-04-02
3: LOC:05-04-05
This code should do what you want:
SELECT *
FROM <table>
WHERE location BETWEEN 'LOC:05-04-01' AND 'LOC:05-04-20'
ORDER BY location DESC;
You are doing string comparisons, and the values compare as strings.
You should test this using a direct query on the database. If this doesn't work, then you might have data in columns that you don't expect -- say the hyphens are really a different character.
If the PHP code does not work, something is going wrong at that level. You might have an error in your query (say connected to the wrong database). You might have bad characters in your constants.
I need to get a SUM off all numerical entries in one of the tables of my DB
id | parameter
--------------
1 | 5
2 | 1
3 | 11
4 | 3
My php is:
$total = 'SELECT parameter FROM resource_table';
$res = $db->prepare($total);
$res->execute();
while($row4 = $res->fetch()) {
$count_sum1[$row4['parameter']][] = $row4;
}
$count_sum = array_sum( $count_sum1 );
print<<<END
$count_sum
END;
this is not working, as I can guess I am not doing something correctly.
Please help
Thanks for your help in advance
Let the database do the work:
SELECT SUM(parameter) FROM resource_table
In case you want to stick to php:
<?php
// code
while($row=$res->fetch())
$count_sum+=row["parameter"];
// code
?>
Yes, database engine supports simple operations, such as SUM(), AVG(), MIN() and lot of others... so actually you are able to do some basic operation on the specific engine. Read a documentation to your database engine, because you could use MySql, MSSQL, or plenty of others and every use its own type of functions.
But I suppose that you use MySQL, so the function is simply SUM():
SELECT SUM(parameter) FROM tableName;
I have in one database rough 2,000 movies with genres store like this:
MOVIE \ ID \ Genre
Avatar \ 1 \ action ^ adventure ^ scifi
matrix \ 2 \ action ^ scifi
and I was trying to make a system that would sort by genre, and when I researched it I found that I needed a table that would connect the two. (see this question: MySQL select genres problem. (php))
So I know how to implement this, I just dont know how I could transfer the genres into a seperate table.
The only way I could come up with is to go row by row and grab the genre column and explode the text, get the array and test for different genres, but that seemed too much of a hassle and difficult to do on 2k+ rows.
Thanks!
The answer you quote in your question seems to have nailed the database strutcure you require. So really it is about replicating this.
Firstly I would create the Genre table. Again much like in the reference quoted the following structure will suffice.
+------------+---------+
| id | genre |
+------------+---------+
| 1 | action |
+------------+---------+
| 2 | drama |
+------------+---------+
and so on. Once you have created the genre table. You will need to create your movie_genre table where the genres will be stored. So for example
+----------+-----------+---------+
| id |movie_id |genre_id |
+----------+-----------+---------+
The following structure. Again like the reference quoted.
Once you have the database structure ready, the next thing would be to create a simple switch function. For example
public function returnGenId($genre)
{
switch($genre)
{
case "action":
return 1;
break;
case "drama"
return 2;
break;
}
}
Obviously the return will match with the id of the genre in the genre table.
You can now get everything from your database by doing
SELECT * from movies
Which should leave you with an array similar to this
array(
[0]=>array(
[id]=>1
[movie]=>Avatar
[genre]=>action ^ adventure ^ scifi
)
)
Once you have your data then just loop through, exploding the genre and creating your new array for example
foreach($results as $key=>$result)
{
$eplosion = explode(' ^ ',$result['genre'];
foreach($explosion as $exploded)
{
$genres[] = returnGenId($exploded);
}
$data[$result['id']] = array('movie'=>$result['movie'],'genres'=>$genres);
}
This should leave with an array like so (as an example, depending on the switch statement)
array(
[1]=>array(
[movie]=>Avatar
[genres]=>array(
[1]=>1
[2]=>3
)
)
)
Now you can loop through the data as put it into the relevant database
foreach($data as $key=>$film)
{
foreach($film['genre'] as $dbGenre)
{
}
}
In the second foreach do a mysql insert into movie_genre using $key as the movie_id and then $dbGenre as the genre_id. By doing this one script you can sort your database tables out and structure them correctly. Although this can be a hassle. Once you have got it out of the way, things will be infinitely easier. Let me know how you get on
Update
I've run these kind of scripts on databases with a couple of hundred thousand rows, so I can't see an issue for a couple of thousand. But this also depends on the memory size set on your server.
Increasing your memory limit may be an idea if need be, see this link:
http://davidwalsh.name/increase-php-memory-limit-ini_set
Another idea is to hash out the last foreach loop and do a print of the data ie
print_r($data);
/*
foreach($data as $key=>$film)
{
foreach($film['genre'] as $dbGenre)
{
}
}
/*
Before executing the script add this as close to the very top (preferably the first line)
$start = time();
Then add this to the bottom. Again as close the to the bottom of the script.
$end = time();
$wait = $end – $start;
echo 'The script took ' . $wait . ' seconds to run';
This will show you the amount of time taken.
Always before messing with the database though, dump the database for safety. Maybe even clone it and run this on a test database for peace of mind.
I think you can create a new table for genres first than you might use SUBSTRING_INDEX(field, '^', 1) in your query to select genres DISTINCT and write it to your new DB table in a single query.(INSERT INTO .... (SELECT ...). Than all you need to do is relate your new table of genres to your movies table. Here is a link for SUBSTRING_INDEX.
In my SQL database I have a query that turns values in multiple rows into a single concatenated string.
id | image_filename | slides | languages | types
-------------------------------------------------------------------------
10 | filename.jpg | 55,4 | 1 | TN,CQ
In PHP I am trying to check to see which slides this image is associated with. If it is associated, that checkbox will be checked.
$isChecked = (strpos($slide,"5") !== false) ? " checked=\"checked\"" : "";
The problem is that the statement above will return true because there is a 5 contained in there. What needs to happen is it will return false because 5 does not equal 55.
How can I create something in PHP to check the values before each comma, and see if it matches a certain string that I can specify.
Thanks!
You should explode($slide) then convert to integers
$parts = explode(',', $slide);
if(intval($parts[0]) == 55) {
// Do stuff
}
Compare the actual values conjoined by the comma!
$isChecked = in_array("5",explode(",",$slide))!=false?" checked=\"checked\"":"";
See explode.
Edit: Just noticed you only want to check the value BEFORE the comma only. This will actually be faster than creating an array from the string:
$isChecked = "5"==strstr($slide,',',true)?" checked=\"checked\"":"";
Assuming you have PHP 5.3+. See strstr
You should actually use the MySQL FIND_IN_SET() function to do this reliably at the RDBMS level. See this SO question, whose answer illustrates your goal.
I'm trying to create a search engine for an inventory based site. The issue is that I have information inside bbtags (like in [b]test[/b] sentence, the test should be valued at 3, whereas sentence should be valued at 1).
Here is an example of an index:
My test sentence, my my (has a SKU of TST-DFS)
The Database:
|Product| word |relevancy|
| 1 | my | 3 |
| 1 | test | 1 |
| 1 |sentence| 1 |
| 1 | TST-DFS| 10 |
But how would I match TST-DFS if the user typed in TST DFS? I would like that SKU to have a relevancy of say 8, instead of the full 10..
I have heard that the FULL TEXT search feature in MySQL would help, but I can't seem to find a good way to do it. I would like to avoid things like UNIONS, and to keep the query as optimized as possible.
Any help with coming up with a good system for this would be great.
Thanks,
Max
But how would I match TST-DFS if the user typed in TST DFS?
I would like that SKU to have a relevancy of say 8, instead of the full 10..
If I got the question right, the answer is actually easy.
Well, if you forge your query a little before sending it to mysql.
Ok, let's say we have $query and it contains TST-DFS.
Are we gonna focus on word spans?
I suppose we should, as most search engines do, so:
$ok=preg_match_all('#\w+#',$query,$m);
Now if that pattern matched... $m[0] contains the list of words in $query.
This can be fine-tuned to your SKU, but matching against full words in a AND fashion is pretty much what the user presumes is happening. (as it happens over google and yahoo)
Then we need to cook a $expr expression that will be injected into our final query.
if(!$ok) { // the search string is non-alphanumeric
$expr="false";
} else { // the search contains words that are no in $m[0]
$expr='';
foreach($m[0] as $word) {
if($expr)
$expr.=" AND "; // put an AND inbetween "LIKE" subexpressions
$s_word=addslashes($word); // I put a s_ to remind me the variable
// is safe to include in a SQL statement, that's me
$expr.="word LIKE '%$s_word%'";
}
}
Now $expr should look like "words LIKE '%TST%' AND words LIKE '%DFS%'"
With that value, we can build the final query:
$s_expr="($expr)";
$s_query=addslashes($query);
$s_fullquery=
"SELECT (Product,word,if((word LIKE '$s_query'),relevancy,relevancy-2) as relevancy) ".
"FROM some_index ".
"WHERE word LIKE '$s_query' OR $s_expr";
Which shall read, for "TST-DFS":
SELECT (Product,word,if((word LIKE 'TST-DFS'),relevancy,relevancy-2) as relevancy)
FROM some_index
WHERE word LIKE 'TST-DFS' OR (word LIKE '%TST%' AND word LIKE '%DFS%')
As you can see, in the first SELECT line, if the match is partial, mysql will return relevancy-2
In the third one, the WHERE clause, if the full match fails, $s_expr, the partial match query we cooked in advance, is tried instead.
I like to lower case everything and strip out special characters (like in a phone number or credit card I take everything out on both sides that isn't a number)
Rather than try to create your own FTS solution, you could try to fit the MySQL FTS engine to your requirements. What I've seen done is create a new table to store your FTS data. Create a column for each different piece of data that you want to have a different relevance. For your sku field you could store the raw sku, with spaces, underscores, hyphens and any other special character intact. Then store a stripped down version with all these things removed. You may also want to store a version with leading zeros removed, as people often leave things like that out. You can store all these variations in the same column. Store your product name in another column, and the product description in another column. Create a separate index on each column. Then when you do your search, you can search each column individually, and multiply the rank of the results based on how important you think that column is. So you could multiply sku results by 10, title by 5 and leave description results as is. You may have to do a little experimentation to get the results you want, but it may ultimately be simpler than creating your own index.
Create a keywords table. Something along the lines of:
integer keywordId (autoincrement) | varchar keyword | int pointValue
Assign all possible keywords, skus, etc, into this table. Create another table, a post-keywords bridge, (assuming postId is the id you've assigned in your original table) along the lines of:
integer keywordId | integer postId
Once you have this, you can easily add keywords to each post as it is interested. To calculate total point value for a given post, a query such as the following should do the trick:
SELECT sum(pointValue) FROM keywordPostsBridge kpb
JOIN keywords k ON k.keywordId = kpb.keywordId
WHERE kpb.postId = YOUR_INTENDED_POST
I think the solution is quite straightforward unless I missed something.
Basically run two search, one is exact match, the other is like match or regex match.
Join two resultsets together, like match left join exact match. Then for example:
final_relevancy = (IFNULL(like_relevancy, 0) + IFNULL(exact_relevancy, 0) * 3) / 4
I didn't try this myself though. Just an idea.
I would add a column that is stripped of all special character's, misspellings, and then upcased (or create a function that compares on text that has been stripped and upcased). That way your relevancy will be consistent.
/*
q and q1 - you table
this query takes too much resources,
make from it update-query ( scheduled task or call it on_save if you develop new system )
*/
SELECT
CASE
WHEN word NOT REGEXP "^[a-zA-Z]+$"
/*many replace with junk characters
or create custom function
or if you have full db access install his https://launchpad.net/mysql-udf-regexp
*/
THEN REPLACE(REPLACE( word, '-', ' ' ), '#', ' ')
ELSE word
END word ,
CASE
WHEN word NOT REGEXP "^[a-zA-Z]+$"
THEN 8
ELSE relevancy
END relevancy
FROM ( SELECT 'my' word,
3 relevancy
UNION
SELECT 'test' word,
1 relevancy
UNION
SELECT 'sentence' word,
1 relevancy
UNION
SELECT 'TST-DFS' word,
10 relevancy
)
q
UNION
SELECT *
FROM ( SELECT 'my' word,
3 relevancy
UNION
SELECT 'test' word,
1 relevancy
UNION
SELECT 'sentence' word,
1 relevancy
UNION
SELECT 'TST-DFS' word,
10 relevancy
)
q1
it is a page coading where query result shows
**i can not use functions by use them work are more easier**
<html>
<head>
</head>
<body>
<?php
//author S_A_KHAN
//date 10/02/2013
$dbcoonect=mysql_connect("127.0.0.1","root");
if (!$dbcoonect)
{
die ('unable to connect'.mysqli_error());
}
else
{
echo "connection successfully <br>";
}
$data_base=mysql_select_db("connect",$dbcoonect);
if ($data_base==FALSE){
die ('unable to connect'.mysqli_error($dbcoonect));
}
else
{
echo "connection successfully done<br>";
***$SQLString = "select * from user where id= " . $_GET["search"] . "";
$QueryResult=mysql_query($SQLString,$dbcoonect);***
echo "<table width='100%' border='1'>\n";
echo "<tr><th bgcolor=gray>Id</th><th bgcolor=gray>Name</th></tr>\n";
while (($Row = mysql_fetch_row($QueryResult)) !== FALSE) {
echo "<tr><td bgcolor=tan>{$Row[0]}</td>";
echo "<td bgcolor=tan>{$Row[1]}</td></tr>";
}
}
?>
</body>
</html>