How to make search engine query in Mysql&PHP? - php

I want to make a search engine in an intranet. Now i use this clause in PHP.
$k = explode(" ",$_GET[key]);
$sql = "select entreprise.*, employee.* where entreprise.* or employee.* like '%$k[0]%' or '%$k[1]%'";
But it seems doesn't work. Do you know where is wrong?
Thanks in advance.
Edit:
$sql = "select * from entreprise, site, salarie where entreprise.*, site.*, salarie.* like '%$k[0]%' or '%$k[1]%'";
I have modified the query clause. With this code, i think you can know what i want to do.
I want to find anything that matches the content in all the columns of entreprise table and the content in all the columns of employee table.

It's hard to exactly see what you're trying to do, but you need, in your SQL query, to specify :
on which tables you are working, with a from clause
on which fields the search has to be done, in the where clause.
how the data between employees and enterprises are related :
do you want to search for entreprises and their employees ?
for employees and there enterprises ?
for all enterprises and the employees when the employee or the enterprise contains the words ?
You could use something like this to search for entreprises that contain the word, and get their employees to :
select *
from entreprise
inner join employee on employee.id_entreprise = entreprise.id
where entreprise.name like '%word%'
or entreprise.description like '%word%';
Or, to search for employees that match the criteria and get their entreprise too :
select *
from employee
inner join entreprise on entreprise.id = employee.id_entreprise
where employee.name like '%word%';
(just some ideas -- you'll have to build from there !)

This:
$sql = "select entreprise.*, employee.* where entreprise.* or employee.* like '%$k[0]%' or '%$k[1]%'";
is not valid SQL. It is hard to guess what you want to do, but I'm trying anyway: you want to find employees, and search them by name or by enterprise that employs them. Is that the case? Or do you want to search employess and/or enterprises?
EDIT
I want to find anything that matches the content in all the columns of entreprise table and the content in all the columns of employee table.
Ok, first of all you should realize that SQL is probably not the best tool for this job. See the other commenter - his suggestions about sphinx and friends are good. But still, if you really want to:
$sql = '
SELECT e.id, e.name
FROM enterprise e
-- first, look in column1
WHERE e.column1 LIKE '."'%".$k[0]."%'".'
OR e.column1 LIKE '."'%".$k[1]."%'".'
...etc for all entries in k...
OR e.column1 LIKE '."'%".$k[N]."%'".'
-- then, look in column2
OR e.column2 LIKE '."'%".$k[0]."%'".'
OR e.column2 LIKE '."'%".$k[1]."%'".'
...and so on and so forth for all entries in $k and all columns in enterprise...
UNION ALL
SELECT s.id, s.name
FROM salarie s
WHERE ...and the same for columns of salarie...
...
UNION ALL
...any other tables you want to search...
';
As you can see, not something that makes you happy.
Another approach that might give you more joy is having some overnight job to scan all rows in the tables you're interested in, parse the texts you want to search into separate words, and store those in a keyword table, and storing the association between an object from the source database and the keyword in a separate table. You can then search the keyword table and use the id's and table names you find for a collection of keywords to build the actual query to retrieve those rows. This is what I do, and it works great. It works better because there is a relatively small amount of words that you will encounter, whereas the collection of objects is quite possible very large.

Related

cant have two where statements in mysql query

I have to search the database for certain results which are in one table but are not in a certain column in another table. my query below is what I have so far.
$sql = "SELECT * FROM users WHERE name LIKE '%".$_POST["search"]."%' AND NOT IN
(SELECT friend FROM friends WHERE user='{$user_name}')";
as you can see I have the WHERE and then I declare the first item it has to search for. But then I add in AND so I am can search another table which is in the brackets.
What is the best way I can do this action without having to change my format to much?
if anyone has any questions please post them below. So I can improve my question quality in the future please post below any ways that I can improve.
The problem isn't the use of two WHERE clauses, it's that instead of writing:
... WHERE name LIKE '%xxx%' AND NOT IN (...) ...
you have to write:
... WHERE name LIKE '%xxx%' AND name NOT IN (...) ...
"SELECT * FROM users left join friends on users.name=friends.friend WHERE friends.friend IS NULL AND users.name LIKE '%".$_POST["search"]."%'"

Get an array of all columns starting with the same characters.

This is quite difficult to explain in the title, so I'll do my best here. Basically I have a column in a MySQL products table that contains rows like:
FEL10
FEL20
FEL30
PRO05
PRO07
PRO08
VAI12
VAI13
VAI14
These are the categories ("FEL","PRO","VAI") and a identification number of my products ("10", "20" and so on). I need an SQL select query that creates me a textual array like:
FEL*
PRO*
VAI*
With this array I need to create a listbox, that allows me to choose a category (regardless of the identification number). Once I choose a category, let's say PRO*, I will need to do the reverse action: print all the products info related to PRO05, PRO07 and PRO08.
How do you think you can achieve this? I have been trying using the DISTINCT statement but I need to filter only the first characters, otherwise it will be useless. I also tried the SUBSTRING() and LEFT() functions, but they seem not to be working (I get an SQL Syntax error).
--
Thanks for your help as always
What is wrong with?
SELECT distinct left(col, 3) as category FROM `table1`
MySQL LIKE to the resque:
SELECT col1 FROM table1 WHERE col1 LIKE 'FEL%';
This way you have to add all cases using OR.
Alternative - REGEXP:
SELECT col1 FROM table1 WHERE col1 REGEXP '(FEL|PRO|VAI).*'
Then it's just a matter of writing proper regex.
I would use extra col to group your items - to avoid such selecting altogether (which should be quite expensive on bigger dataset).
https://dev.mysql.com/doc/refman/5.1/en/regexp.html#operator_regexp
To get the list of the 3-letter codes use:
select distinct left(combicode, 3)
from mytable;
When a user selects one of the values use this to get all matching entries:
select *
from mytable
where combicode like concat(#category, '%');
(Aside from that: It's a bad idea to have concatenated values in one column. Why not have one column for the category and another for the product code? Then there would be no problem at all.)

how can i add condition in mysql query executed in another table?

I develope a website for E-books, i have in database table for authors and table for publishers .. sometimes the author name is added also in publishers table as a publisher
Now i have his name as an author and a publisher .. when i search in the site for his name, it return twice because i search in authors table and in publishers table then merge two queries
this is my code :-
function generate_results($keyword, $row = 0) {
$result1 = $this->db->query("SELECT au_id,au_name,au_state,SUBSTR(au_info,1,190) AS au_info,au_img FROM d_author where (au_name LIKE '%$keyword%' or au_info LIKE '%$keyword%') and au_state = '1' limit $row,20");
$result2 = $this->db->query("SELECT pub_id,pub_name,pub_state,SUBSTR(pub_info,1,190) AS pub_info,pub_img FROM d_publishing where (pub_name LIKE '%$keyword%' or pub_info LIKE '%$keyword%') and and pub_state = '1' limit $row,20");
$results = array_merge($result1->result_array(), $result2->result_array());
return $results;
}
Now i want to modify the second query to something like that :
select all publishers from "publishers table" where the name of publisher is like $keyword and this $keyword doesn't exist in authors table ..
I mean if this name exist in authors don't select it in publishers
How can i translate that meaning to Mysql Query
First, check out sql-injections before continuing to develop in your ebook-application. Looks like your keyword is not checked to be a safe parameter. And just to be sure, do you know about csrf and xss? If not, check about that too. This is very important.
Secondaly, you should consider working on your database design to avoid having duplicated values. Check out "database normalization" for more information. Seems like you could do another table to extract your "contact information" like name, state, id etc. This would make it possible for your author-table and publisher-table to use a "contact_id" referencing the contact-information-table.
Last but not least, to answer your question, you can generelly solve such problems with an "anti join". Use a left join on the authors table in the second query and check for "IS NULL" on matches with the publisher table. More information here: http://explainextended.com/2009/09/18/not-in-vs-not-exists-vs-left-join-is-null-mysql/
I do not know if I understand your database design completly right, but it also seems like an UNION combined with a DISTINCT could help you - and you wouldn't even need this array_merge-stuff. I would suggest you to check out these two commands in the mysql docs.

PHP/MySQL If FROM Statements

sorry for the extremely basic question!! I'm very new to PHP/MySQL
How would it be possible to do an if statement referencing wherever or not data was from a certain table.
Would this work?
if ( $search FROM "table2" )
{
function for table2.. etc
}
TABLE:INSTRUMENTS
COLUMNS:
id instrument grade standard comments
instrument2 grade2 standard2 comments2
instrument3 grade3 standard3 comments3
instrument4 grade4 standard4 comments4
instrument5 grade5 standard5 comments5
TABLE: PEOPLE
COLUMNS:
id first last snumber course email graduate inumber
Basically a person from the PEOPLE table is linked via ID to instruments in the INSTRUMENTS table, I have an e-mail search function that I need to send out the relative data to the relative instruments.
I want to get the comments[i] , grade[i], standard[i] of the matching instrument[i]
Somewhere in your code you must already have specified the table to select from. You can use the same logic to see which table you initially used?
For example:
$sTable = 'table2';
$rResult = mysql_query(sprintf($sQuery, $sTable));
if ($sTable == 'table2') { // use $rResult }
You know what table it came from, because you retrieved it from that table.
Update
Perhaps:
$search = trim(stripslashes($_POST['search']));
$search = mysql_real_escape_string($search);
//Find instruments searched for:
$query = "
SELECT *,
('$search' IN `instrument`) AS `matched1`,
('$search' IN `instrument2`) AS `matched2`,
('$search' IN `instrument3`) AS `matched3`,
('$search' IN `instrument4`) AS `matched4`,
('$search' IN `instrument5`) AS `matched5`
FROM `instruments`
WHERE '$search' IN (`instrument`, `instrument2`, `instrument3`, `instrument4`, `instrument5`)
";
Explore the results and find out how to use them to your advantage.
This isn't the most glamourous solution and you can no doubt improve this with a different approach, but it's something to get you started.
Hmm,
The tables need a redesign IMHO.
I would change table instruments to.
id, people_id, instrument, grade, standard, comments
This query:
SELECT
people.email
,instruments.instrument
,instruments.grade
,instruments.standard
,instruments.comment
FROM people
INNER JOIN instruments ON (instruments.people_id = people.id)
WHERE people.id = 10
Will give you all instruments for person number 10.
You can change the where clause to where people.snumber = x or whatever you feel like.
Or add extra clauses to limit the number of instruments by adding something like : AND instrument.grade > 7 at the end
With this setup people can have any number of instruments.
It feels a bit odd to -reverse link- the instruments to people like this, but believe me... it works.
I recommend reading up on joins (google 'mysql join') and always use explicit joins using the join keyword, it makes understanding your queries much easier.
If this is the result you where looking for, then you can drop the inumber field from the people table, since we moved the link between people and instruments to the instrument table.
On an 1-to-many link the linking field should always be on the 'many'-table.
You would need to store what table the search result was from in a variable, and compare the two variables.
if($search === "table2")
There is no from operator in PHP.

Mysql Unique Query

I have a programme listing database with all the information needed for one programme packed into one table (I should have split programmes and episodes into their own) Now since there are multiple episodes for any given show I wish to display the main page with just the title names in ascending and chosen letter. Now I know how to do the basic query but this is all i know
SELECT DISTINCT title FROM programme_table WHERE title LIKE '$letter%'
I know that works i use it. But I am using a dynamic image loading that requires a series number to return that image full so how do I get the title to be distinct but also load the series number from that title?
I hope I have been clear.
Thanks for any help
Paul
You can substitute the DISTINCT keyword for a GROUP BY clause.
SELECT
title
, series_number
FROM
programme_table
WHERE title LIKE '$letter%'
GROUP BY
title
, series_number
There are currently two other valid options:
The option suggested by Mohammad is to use a HAVING clause in stead of the WHERE clause this is actually less optimal:
The WHERE clause is used to restrict records, and is also used by the query optimizer to determine which indexes and tables to use. HAVING is a "filter" on the final result set, and is applied after ORDER BY and GROUP BY, so MySQL cannot use it to optimize the query.
So HAVING is a lot less optimal and you should only use it when you cannot use 'WHERE' to get your results.
quosoo points out that the DISTINCT keyword is valid for all listed columns in the query. This is true, but generally people do not recommend it (there is no performance difference *In some specific cases there is a performance difference***)**. The MySQL optimizer however spits out the same query for both so there is no actual performance difference.
Update
Although MySQL does apply the same optimization to both queries, there is actually a difference: when DISTINCT is used in combination with a LIMIT clause, MySQL stops as soon as it finds enough unique rows. so
SELECT DISTINCT
title
, series_number
FROM
programme_table
WHERE
title LIKE '$letter%'
is actually the best option.
select title,series_number from programme_table group by title,series_number having title like '$letter%';
DISTINCT keyword works actually for a list of colums so if you just add the series to your query it should return a set of unique title, series combinations:
SELECT DISTINCT title, series FROM programme_table WHERE title LIKE '$letter%'
Hey thanks for that but i have about 1000 entries with the same series so it would single out the series as well rendering about 999 programmes useless and donot show.
I however found out away to make it unique and show the series number
SELECT * FROM four a INNER JOIN (SELECT title, MIN(series) AS MinPid FROM four WHERE title LIKE '$letter%' GROUP BY title) b ON a.title = b.title AND a.series = b.MinPid
Hopefully it helps anyone in the future and thank you for the replies :)

Categories