PHP/MySQL If FROM Statements - php

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.

Related

Ordering users with most matching user's skills

I want to show recommended users to a user in descending order where skills match the most.
Issue is that I am storing skill in single field in this form
user_skill
musician,pop,singer
Note: this will be input musician,pop,singer..
so what I want to achieve I want to show users have all three skills at top,then those having two at last those having only one.
so out put will be like
**user_name skills**
sam musician,pop,singer
smith musician,pop,singer
ali musician,singer
nasira musicain,pop
siri musician
taylor pop
andrew singer
Can this be achieved by single mysql query?
If this not possible can this be done by php code.I don't want to change table structure as this will require lots of redo.
Thanks for your help.
You might be able to do with with SQL but the query would be so complex i probably wouldnt.
On the php side you could iterate over the result set and tally the skills for each user_name within a given set of skills you are looking for, and then just sort them:
$desired = explode(',', $input);
$users = array();
// i presume you have the query worked out to find users with any one of input
// skills attributed to them so lets say that $stmt is the PDO statement where you
// have executed that query
while (false === ($row = $stmt->fetch(PDO::FETCH_ASSOC))) {
$row['skills'] = explode(',', $row['skills']);
// assign an array containing only skills that were in your $input
// to $row['desired_skills']
$row['desired_skills'] = array_intersect($desired, $row['skills']);
$row['nb_desired_skills'] = count($row['desired_skills']);
$user[] = $row;
}
usort($users, function ($a, $b) {
return $b['nb_desired_skills'] - $a['nb_desired_skills'];
});
// now you can loop over $users and display the fields you need
However, the definition and attribution of these skills is a key part of you application, you should just normalize the tables now... its only going to become a larger refactor by putting it off.
I don't want to change table structure as this will require lots of redo.
I strongly (!) recommend you make a separate skills table, and link that to your users table using foreign keys. You will be infinitely thankful to yourself once your project gets even slightly more complex.
If you don't know how, I'm sure people on this site would help you with a script that does the conversion if you were to post another question.
MySQL
CREATE TABLE skills
(
name VARCHAR(64) NOT NULL,
user_id INT NOT NULL,
PRIMARY KEY (name, user_id),
FOREIGN KEY (user_id) REFERENCES users(id)
);
This way you can easily select users by most skills using a simple subquery (assuming you have a users table with an id column):
MySQL
SELECT *,
(SELECT COUNT(*)
FROM skills
WHERE user_id = u.id) AS num_skills
FROM users u
ORDER BY num_skills DESC;
So why would you take this approach instead of relying on PHP?
Creates minimal extra overhead in database,
significantly reduces chatter between database and webserver by not requiring to query the entire users table if you just want, for example, only the top 10 users,
enables more complex and varying queries in the future easily.
The following MySQL snippet queries only those users who have a given skill (for example, "singer"), then sorts them in descdending order based on number of skills. The query does not return users with zero skills:
MySQL
SELECT *,
(SELECT COUNT(*)
FROM skills
WHERE user_id = u.id
AND name = 'singer') AS num_skills
FROM users u
WHERE num_skills > 0
ORDER BY num_skills DESC;
Of course, you can also search for skills by id just replace the second part of the WHERE clause inside the subquery with AND id = 3, which will query those users, who have a skill with ID of 3.
The next step towards a more optimal database would be creating a real skills table, which stores only the skills that you have registered in your database, and a user_skills table, that links it and the users table together.
This would enable you to significantly reduce database size on the long run, and be able to run complex but 'clean' queries that do not depend on the webserver.

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.

How do I search multiple mySQL tables to find one specific row?

I have three tables: adapters, connectors, components
I need to be able to search them all to find a corresponding Part Number (part_num)
The part number is unique so I don't have to worry about multiple entries.
I use GET to find the part number in the URL, set it to $num, and then do the SELECT
What I've found is that I should use UNION, however the three tables have different columns and it gives me an error when trying to do the select. In the example below
Using UNION to find references from other tables
This is my code:
if(isset($_GET['num'])) {
$num = $_GET['num'];
$result = mysql_query("SELECT * FROM connectors WHERE part_num = '$num' UNION SELECT * FROM adapters WHERE part_num = '$num' UNION SELECT * FROM components WHERE part_num = '$num'"); }
Any help would be appreciated, so thanks in advance SO =)
You should probably have a fourth table Parts that identifies to which type table each part_num has been allocated. However, without that, you could still get what you're after with outer joins (wasteful though):
SELECT * FROM
connectors
LEFT JOIN adapters USING(part_num)
LEFT JOIN components USING(part_num)
WHERE
part_num = ?
Note that I have used ? as you really should be using prepared statements: if you don't know why, or what they are, read about Bobby Tables.
How about taking not all columns, but only titles or so on?
$sSql = "SELECT id, title, 1 FROM connectors WHERE part_num = '$num'
UNION
SELECT id, title, 2 FROM adapters WHERE part_num = '$num'
UNION
SELECT id, title, 3 FROM components WHERE part_num = '$num'";
You must adopt it to your table fields, but with this logic you will have an array where by the Third column (in my example), you can know if it is connector, adapter or component found, then generate proper links or do other actions with this data.
Another Way is to make Multi query, which will return multiple results by one database request. There are some ways to use it - using mysqli (http://lt.php.net/manual/en/mysqli.multi-query.php) or some of Adodb or PDO libraries.
Hope it will help.
To use UNION, the 3 recordsets must have the same number of columns, so you'll have to specifed which columns from each table that you want. From there, you'll have a single results set with the data from each of the 3 queries.

How to make search engine query in Mysql&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.

Mysql: Getting Count of Comma Separated Values With Like

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.

Categories