I am trying to add filters to a DB search. I have a search that takes some text and tries to find items with that text in the title. I also have a price range filter. That code is below and works just fine
$sql = "SELECT * FROM items where title LIKE '%". $title ."%' AND price > '". $price1 ."' AND price < '".$price2."' Limit 70";
Now I am trying to more and more filters. Is there a select from the above code's output? I don't want to just keep making a longer SELECT statement with tons of if statements. I'd prefer to take the output of the previous select and refine that with another select. Is this possible?
EDIT 1 Context:
Users are the ones entering the information. This is for searching the items on my site.
There's no other useful way than adding lots of different conditions to your WHERE cause, if you use plain SQL. It is possible to use several nasted SELECT statements in your query, but this makes your code neither any more readable nor faster.
A more elegant solution is the usage of query objects or another form of object-oriented query abstraction (e.g. ZendDB).
You can use some of the mysql string functions like INSTR(), MATCH which will make your life a little easy and also help the readability of the code.
You can also use REGEXP and NOT REGEXP for pattern matching . The list of string functions are here.
Related
This is a bit of a complicated issue to explain but here goes:
I have an SQL statement:
SELECT
SUM(time.timein),
time.reasonforabsence
WHERE
staff.id = time.staff_id
AND
staff.department_id = department.id
AND
(staff_name LIKE '%$staffsearch%')
GROUP BY
staff.id
ORDER BY
time.dateadded
ASC;
From this statement I need to pull the values time.reasonforabsence but as this is text and the statement is grouped, I cannot seem to do this. Does anyone know if there is a way for me to pull them possibly into a PHP array.
The time.reasonforabsence has multiple possible values.
Sorry for the vagueness I am writing this in a rush. Let me know if there is anymore info needed and I will add it tomorrow.
What you can do is return an aggregated string
SELECT
SUM(time.timein),
GROUP_CONCAT(time.reasonforabsence)
...
You can optionally use DISTINCT if you don't want repeated reasons. On php you'll have split them
Is there any reason why you should separate query and result when writing code, other than maybe readability?
Example separate:
$query = "SELECT * FROM foo ORDER BY foo2 DESC LIMIT 10";
$result = mysqli_query($dbconnect,$query);
compared to single line:
$result = mysqli_query($dbconnect,"SELECT * FROM foo ORDER BY foo2 DESC LIMIT 10");
I usually use the 1st example but have found myself using the 2nd single line example more and more of late as its quicker and easier to write so thought I'd ask before it becomes 2nd nature and then find out its really bad and may blow up the world or something 0.o
This is more of a preference, but readability is certainly a strong justification. However, I would also argue that scalability and maintainability of the query might also be a fitting arguments as well. suppose you have a complex query with multiple variables being sanitized for SQL injections with joins as so forth. In other words a long query:
$result = mysqli_query($dbconnect,"SELECT * FROM foo, bar Where col1.bar = (Select col1 From someTable where {$varibale} = ...) Group By ... ORDER BY foo2 DESC LIMIT 10");
Stuffing all of that into the function makes it difficult to read and anoying to maintain as well.
To give an answer to this question. Do like you want (or almost).
Like I said, the first way is maybe used due to the historical where we was limited to 80 characters. But this restriction doesn't exist anymore (and we have bigger screens). By the way, I don't tell you to put 300 characters per line.
Use the one you feel more readable / maintainable with. The only drawback can be your coworkers. They can dictate which one you must use.
Actually you could write your whole source in one line.
(Minimize source = Delete all spaces and linebreaks)
of course not in strings :)
Effect is: (1 Positive and 3 Negative to do this)
Bad readability (-)
Faster parsing (+)
Slow editing source (-)
No good maintainability (-)
Not writing everything to one line
Effect is: (3 Positive and 1 Negative to do this)
Good readability (+)
Little bit slower parsing (-)
Fast editing source (+)
Better maintainability (+)
(Guess you only feel the parsingtime difference in very large codefiles)
This is how I decide to write my source.
Sometimes (for e.g. Plugins) I use the minimized version.
for me, its all about readability. I write a ton of code. and release app. 6 months later when i go back to fix a bug, I need to quickly find things. I separate out as much as I can. Parsing times are minimal unless you are writing incredibly large volumes of code. its all about readabilty for me. I go one step further to make it as pretty as possible.
$select = "SELECT x,y,z";
$from = " FROM foo,bar,table3";
$order = " ORDER BY foo2 DESC ";
$limit = " LIMIT 10";
$query = $select . $from . $order . $limit;
$result = mysqli_query($dbconnect,$query);
I think it's just a preference too. I usually use the short way for short and "unvarying" requests.
But for longer requests, it's easier to read and maintain taken separately.
Especially for "dynamic requests" (partly depending on external conditions): it's sometimes easier to work on a string, for example to concatenate a where clause, or another, or none at all, depending on a condition.
An example I have in mind: a "list.php" script displaying all articles if called with no parameter, and filtering articles of a specific category 'foo' if called with get-parameter ?cat=foo given.
I personally find it easier to read and maintain like this:
$query="select name, description, price from articles";
if(isset($_GET['cat'])) $query.=" where cat={$_GET['cat']}";
$result = mysqli_query($dbconnect,$query);
Of course it could also be done directly in the one-line version using ternary (?:) operators, but then readibility suffers a bit:
$result = mysqli_query($dbconnect,"select name, description, price from articles".(isset($_GET['cat'])?" where cat={$_GET['cat']}":""));
It becomes really much more unreadable and unmaintainable if you add other conditions. For instance, a second filter on get-parameter `?supplier=bar"...
[EDIT:] I just had the case: when your request fails, it's easier to debug when the query stands in a string. A simple echo $query; allows you to see exactly what you're sending to the DB server...
In following php code: $query="select * from $userTable where id=:uid";, you might oversee that $userTable wasn't defined...
but after an echo $query;, you can't oversee that there's something missing here: $query="select * from where id=:uid";...
I have a list of customer in a database with a column name is postcode
At the moment my search runs the SQL
SELECT *
FROM customer
WHERE postcode LIKE '%".$_POST["search term"]."%'
Which works fine but if a row in the databse has the postcode of (SS1 1AB) and someone types in (SS11AB) how can I make it find the correct row?
Basically I want to be Able to search every single combination etc
Only way you could probably do is to with either a regex or white space replacement.
PHP: $term = str_replace(' ', '', $_POST["search term"]);
Query: Select * from customer where REPLACE(postcode, ' ', '') LIKE '%".$term."%'
Having said that however, you'd be far better off formatting the data on insert, because as your table grows, that lookup will become more and more expensive to run. One of my pet hates is websites that use a post code as authentication or verification data, then force you to use a particular notation. I've seen people hypenate the space in their post code before too, so you should always normalise the format before inserting it, or enforce a format (i prefer the former option, but the latter is easier).
Also your query is vulnerable to injection exploits. But thats another topic
Besides the SQL injection, Which you should sort out.
The column should be SS11AB, then query on str_replace(" ", "", $_POST['search term'])
you can make your column look like that by
update customer set postcode = replace(postcode, " " , "")
That will remove all spaces in the column, Then you just need to query without the space with the function above
Mysql allows regular expression matches which would be one way. What I would do though is standardize on a single correct representation in the database - and validate input against that. This would avoid SQL injection issues and make matching easier. It would also allow you to filter out typos when data is entered into the database.
For example, if I search for 'cat' I get all the titles with the word 'cat' in it, such as 'cat in the hat'.
If I type in 'cat hat' I should get back 'cat in the hat', but the query returns empty, because its looking for exactly 'cat hat' and ignoring 'cat in the hat'.
I need some sort of select where it looks up all titles with any word I search for, then does that for the next word, etc... and then... I dont know, some sort of big AND thingy...
So far Im playing with somethign like:
$query = "SELECT title
FROM books
WHERE TITLE LIKE '%" . $search . "%' LIMIT 0,75;";
Probably need some sort of recursive function where it breaks the search input into an array of strings and does a search on each of those then merges them.
Ideas?
You are looking for MySQL Full-Text Search
$query = "SELECT title
FROM books
WHERE TITLE LIKE '%" . $search1 . "%' AND LIKE '%" . $search2 . "%' LIMIT 0,75;";
You need to add an AND clause for each search term. You could also add an OR if you wanted. They would give different results. OR would have a greater number of results and AND would of course be way more specific.
You should be able to do this with an array of inputs if it is simply querying against one field. If it's multiple fields, you'll have to do it using a map.
One thing I would like to point out is that this looks suspiciously like a target for SQL injection. Please be very wary when concatenating SQL queries together in a string. The final result must be escaped and / or parameterized to prevent users from running arbitrary SQL.
Answers:
Split the $search on normal symbols and white space and then build the query
Use MySql Full Text Search
Pitfalls:
Full SQL text search is the better option it will result in faster results. Also be aware that your current query is vulnerable to SQL Injection please use mysqli::real_escape_string to avoid this.
Thanks
I was recently trying to do a project*, which caused me to ask this question. Although since then I've found an alternative solution, I am still curious if what I envisioned doing is, in any way, possible.
Essentially, I am wondering if there is anyway to perform a MySQL query on a MySQL query result in php. For example:
$result = mysql_query("SELECT * FROM foo WHERE bar=".$barValue);
AND THEN, be able to perform multiple queries on $result:
$newResult = mysql_query("SELECT * FROM $result WHERE otherBar=".$barValue);
OR
$otherNewResult = mysql_query("SELECT * FROM $result WHERE otherOtherBar=".$barValue." ORDER BY foobar ASC");
AND so on and so forth...
I realize that I could append the original query with my new WHERE statements and ORDER BYs, but that causes my to query the database unnecessarily and it prevents me from writing more objected oriented code (because I can't pass around a result to be queried, but rather have to requery the database in every function...)
Any advice, pieces of code, frameworks, or ramblings appreciated.
*BTW, my project was having to query a large database of people for people born in certain age groups and then query those age groups for different demographics.
Edit
No, writing a custom function to query the database is not worth the object-orientation (and modifiability) it would give me
You could do a nested query in the same SQL query and keep PHP out of it:
'SELECT * FROM (SELECT * FROM foo WHERE bar="something") AS q1 WHERE q1.bar2 = "something else"'
The question has already been answered. However following explanation will help someone who might be interested in knowing the details of it.
What are Nested query / subquery:
Subqueries are also known as nested queries. A subquery is a SELECT statement within another statement. MySQL supports all SQL standards and additionally provides MySQL specific features.
Why should I use Subquery:
Subquery is structured and it is possible to isolate each parts of statement
Subquery is more readable that complex joins and unions
Subquery provides alternative means to perform action which otherwise would require complex joins and unions
What Subquery returns:
A subquery can return a single value, a single row, a single column, or a table. These are called scalar, column, row, and table subqueries.
Reference: http://dev.mysql.com/doc/refman/5.7/en/subqueries.html
http://www.w3resource.com/sql/subqueries/nested-subqueries.php