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.
Related
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"]."%'"
Would it be possible to store a "link" to another record inside a record? For example:
table USERS
id name link
-------------------------------------------------------
1 user1 [link to record with id=4 in table info]
So, in PHP, I could do something like this:
// connect to the database etc....
$query = "select * from users where id=1";
$result = mysql_query($query);
$another_result = mysql_result($result, 0, 'link');
So that $another_result stores the result of another query, in the same raw format as if it was called using mysql_query().
Is this possible?
$query = "select info.* from info
inner join users on users.link = info.id
where users.id=1";
$result = mysql_query($query);
Using JOIN is a fundamental part of SQL, like using for loops in PHP.
Read A Visual Explanation of SQL Joins by fearless leader.
Maybe you mean a key that point to a another key in another table, so for example you can have something like this :
table USERS
id name info_id
-------------------------------------------------------
1 user1 4
table INFO
id info
--------------
4 someinfo
With a JOIN you can get for example a resultset with the "linked" fields :
SELECT u.name AS name, i.info AS info
FROM USERS u
JOIN INFO i ON u.info_id = i.id
MySql is a so called relational database and having relations (links) between tables is one of the key concepts. In your specific case the "link" you want is called a Foreign Key. You might want to have a read here (there are many more articles around if you have a look on google).
You can retrieve linked records via a JOIN operation as the other answerers have already told you.
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.
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.
I decided to use favs (id's of users which marked that post as a favorite) as a comma separated list in a favs column which is also in messages table with sender,url,content etc..
But when I try to count those rows with a query like:
select count(id)
from messages
where favs like '%userid%'
of course it returns a wrong result because all id's may be a part of another's
For example while querying for id=1 it also increase the counter for any other content that is favorited by user id 11...
Can you please tell me your idea or any solution to make this system work?
With a few or's, you can have an ugly solution:
select count(id) from messages where favs like 'userid,%' or favs like '%,userid,%' or favs like '%,userid'
There's likely a more elegant solution, but that one will at least return the result you're looking for, I believe.
Is it possible to change your data model such that the association between users and their favorite messages is instead stored in another table?
Storing the associations in a single column negates the advantages of a relational database. You pay a performance cost using the like function, you can no longer store additional data about the relationship, and the data is harder to query.
An alternative model might looking something like this (can't include an image since I'm a new user, but I made one here):
users
- id
messages
- id
favorite_messages
- user_id (foreign key to users.id)
- message_id (foreign key to messages.id)
With that in place, your original query would be simplified to the following:
select count(1) from favorite_messages where user_id = userid
Additionally, you can do things like get a list of a user's favorite messages:
select
*
from
messages
inner join favorite_messages
on messages.id = favorite_messages.message_id
where
user_id = userid
should using this :
SELECT count(id) FROM messages WHERE FIND_IN_SET('userid',favs) > 0
You might have to get the value, explode it with PHP and then count the array.
There are ways to do it in MySQL, but from what I've seen, they are a hassle.