Why doesnt this complex MySQL query work? - php

I have 2 tables; members and teams
members table
memberID, firstName, lastName
(firstName and lastName are fulltext indexes)
teams table
team_id, member1ID, member2ID
Here's my query
$sql = "SELECT a.* ";
$sql .= "FROM teams a WHERE ";
$sql .= "a.member1ID IN (SELECT b.memberID FROM members b ";
$sql .= "WHERE MATCH(b.firstName, b.lastName) AGAINST('$q' IN BOOLEAN MODE)) ";
$sql .= "OR a.member2ID IN (SELECT b.memberID FROM members b ";
$sql .= "WHERE MATCH(b.firstName, b.lastName) AGAINST('$q' IN BOOLEAN MODE)) ";
if($year)
$sql .= "AND a.team_y = $year ";
$sql .= "ORDER BY a.team_num ASC ";
if($limit)
$sql .= "$limit";
This query has to be close, but its not working yet.
Im trying to build a query that will let me show me all of the teams "$q" is on.
Ex. $q=doe , Show me all teams that doe is on.
This query has to output the teams.

One possible reason your query doesn't work is there is a minimum length on full-text searching, which defaults to 4 characters. "doe" would fail this match. You can increase this via variable "ft_min_word_len"
http://dev.mysql.com/doc/refman/5.1/en/server-system-variables.html#sysvar_ft_min_word_len
By the way, if you want to avoid Normalizing (which isn't always the "best" way to go), you could at least use JOIN's instead of sub-selects.. e.g. (field names renamed to save on typing)
select t.* from teams t
inner join members me1 on t.m1 = me1.id
inner join members me2 on t.m2 = me2.id
where MATCH(me1.fname, me1.lname, me2.fname, me2.lname)
AGAINST('smith' IN BOOLEAN MODE);

Normalize your database.
In your case, this would mean having a table Team (team_id, name, whatever else), a table Member (member_id, first_name, last_name), and a table MemberToTeam (member_id, team_id). In other words, move the member1ID and member2ID into their own table.
Following this practice, apart from "improving" your database schema in the general sense, means that the query that bothers you will become trivial to write.
If you know the member_id:
SELECT team_id FROM MemberToTeam WHERE member_id = 1
If you search by first or last name:
SELECT mtt.team_id FROM Member m
LEFT JOIN MemberToTeam mtt ON m.member_id = mtt.member_id
WHERE m.first_name LIKE '%your search string here%' OR m.lastname LIKE '%your search string here%'

Related

Make multiple queries in codeigniter and the results based in the first one

I want to display all rows of table article, and for each of article row i want get the SUM of votes from another table (likes), and this with one query.
Here what i have:
$query = "SELECT article.title,article.tags,article.description,article.slug,users.username,article.photo,article.id,article.date,SUM(likes.votes) as upvotes
FROM article";
$query .= " LEFT JOIN users ON article.user_id = users.user_id ";
$query .= " LEFT JOIN likes ON likes.article_id = article.id ";
But my problem with this query, i get only one row ! because in table likes there only one row ...
I want to display results based on article table (i have about 50 rows in it)... and if there nothing related to votes for a specific article, we show (0 votes).
Thank you.
Add group by to the code :
$query = "SELECT article.title, article.tags, article.description, article.slug, users.username, article.photo, article.id, article.date, SUM(likes.votes) as upvotes FROM article";
$query .= " LEFT JOIN users ON article.user_id = users.user_id ";
$query .= " LEFT JOIN likes ON likes.article_id = article.id ";
$query .= " GROUP BY article.id";
Or use codeigniter method:
$this->db->select("article.title, article.tags, article.description, article.slug, users.username, article.photo, article.id, article.date");
$this->db->select("SUM(likes.votes) as upvotes", false);
$this->db->from("article");
$this->db->join("users","article.user_id = users.user_id");
$this->db->join("likes","likes.article_id = article.id");
$this->db->group_by("article.id");
$query = $this->db->get();
return $query->result_array();
A stored function is a special kind stored program that returns a single value. You use stored functions to encapsulate common formulas or business rules that are reusable among SQL statements or stored programs.
Here you query should
$query = "SELECT article.title,article.tags,article.description,article.slug,users.username,article.photo,article.id,article.date,custom_SUM(article.id) as upvotes
FROM article";
$query .= " LEFT JOIN users ON article.user_id = users.user_id ";
and custom mysql function
DELIMITER $$
CREATE FUNCTION custom_SUM(p_article_id int(11)) RETURNS VARCHAR(10)
DETERMINISTIC
BEGIN
DECLARE likes varchar(10);
SET likes =(select sum(likes.votes) from likes where likes.article_id=p_article_id);
RETURN (likes);
END
refer link here http://www.mysqltutorial.org/mysql-stored-function/

How to create such query?

I have four tables:
tournaments (id, name, slots, price, gameId, platformId)
games (id, name)
platforms (id, name)
participations (id, tournamentId, playerId)
I want to get tournament's game name, platform name, slots, price, reservedSlots (participations count), information whether some player (his id is provided by php) participate in this tournament (bool/true) and conditions are:
- gameId must be in specified array provided by php
- platformId must be in specified array provided by php
I have created something like this but it doesn't work correctly:
php:
$platformsList = "'". implode("', '", $platforms) ."'"; //
$gamesList = "'". implode("', '", $games). "'";
mysql:
SELECT
t. NAME AS tournamentName,
t.id,
t.slots,
p. NAME,
g. NAME AS gameName,
t.price
FROM
tournaments AS t,
platforms AS p,
games AS g,
participations AS part
WHERE
t.PlatformId = p.Id
AND t.GameId = g.Id
AND t.Slots - (
SELECT
count(*)
FROM
participations
WHERE
TournamentId = t.id
) > 0
AND part.TournamentId = t.Id
AND t.PlatformId IN ($platformsList)
AND t.GameId IN ($gamesList)
I will not dwelve into handling your post and get values, I will assume that everything is all right:
$possibleGameIDs = getPossibleGameIDs(); //function will return the array you need for possible game id values. Inside your function make sure that the id values are really numeric
$possiblePlatformIDs = getPossiblePlatformIDs(); //function will return the array you need for possible platform id values. Inside your function make sure that the id values are really numeric
$playerId = getPlayerId(); //function returns the player id and makes sure that it is really a number
$sql = "select games.name, platforms.name, tournaments.slots, tournaments.price, ".
"(select count(*) from participations where participations.tournamentId = tournaments.tournamentId) as reservedSlots, ".
"(select count(*) > 0 from participations where participations.tournamentId = tournaments.tournamentId and playerId = ".$playerId.") as isParticipating ".
"from tournamens ".
"join games ".
"on tournaments.gameId = games.id ".
"join platforms ".
"on tournaments.platformId = platforms.id ".
"where games.id in (".implode(",", $possibleGameIDs).") and ".
" platforms.id in (".implode(",", $possiblePlatformIDs).") and ".
" tournaments.slots > 0"
Code was not tested, so please, let me know if you experience any problems using it. Naturally you need to run it, but as you did not specify what do you use to run the query, I did not allocate time to deal with technical details of running it. Beware SQL injections though.

PHP/MYSQL SEARCH QUERY RETURNS ERROR: Subquery returns more than 1 row

please I am totally new to mysql, my problem is:
I have a table called 'cong' which has the following columns(id, sort_code, pin, name, state, lga, zip, address, min, min_photo, sec, min_phone, sec_phone) which contains all congregations.
The columns (state, lga) contains the id from the tables 'states' and 'local_govt'.
The 'states' table has the following columns (id, country_id, name), and the 'local_govt' table has the following columns (id, country_id, state_id, name).
I want to carry out a search on the 'cong' table which should search through the 'state' and 'local_govt' tables for matches, below is the search function I wrote:
<?php
function find_cong($term) {
$query = "SELECT * FROM cong";
$query .= " WHERE state rLIKE
(SELECT id FROM states WHERE upper(name) rLIKE '{$term}')";
$query .= " OR lga rLIKE
(SELECT id FROM local_govt WHERE upper(name) rLIKE '{$term}')";
$query .= " OR upper(name) rLIKE '{$term}'";
$query .= " OR upper(address) rLIKE '{$term}'";
$query .= " OR upper(sort_code) rLIKE '{$term}'";
$query .= " OR upper(pin) rLIKE '{$term}'";
$query .= " OR upper(zip) rLIKE '{$term}'";
$query .= " OR upper(min) rLIKE '{$term}'";
$query .= " OR upper(sec) rLIKE '{$term}'";
$query .= " OR upper(min_phone) rLIKE '{$term}'";
$query .= " OR upper(sec_phone) rLIKE '{$term}'";
$result = mysql_query($query);
confirm_query($result);
return $result;
}
function confirm_query($query) {
if (!$query) {
die("Database query failed : " . mysql_error());
}
}
?>
The problem now is that, it searches some terms and comes up with accurate results, but for some specific terms like local_govt and state names it pops an error:
(Database query failed : Subquery returns more than 1 row)
Please I need your help as I don't have any idea how to write the code better than that.
Thanks.
You have subequeries in the states and local_govt portions of the WHERE statement. Presumably there are rows for a given value of $term where those queries will return a resultset of more than one row. Because you are using rLIKE, which expects to evaluate against one value (rather than multiple), the overall query will error out.
Instead, refactor as follows:
$query .= " WHERE state IN (SELECT id FROM states WHERE upper(name) rLIKE '{$term}')";
$query .= " OR lga IN (SELECT id FROM local_govt WHERE upper(name) rLIKE '{$term}')";
this will account for that contingency.
Please note that the query as written is unlikely to be very performant. Since you are scanning many different columns, it would be best to try not to use regex here, because the optimizer won't be able to leverage indices. Ideally, reduce it to a constant, so that you can use:
SELECT * FROM cong WHERE $term IN (upper(name), upper(address)...)
but that may not be possible given your requirements. If that's the case, I would probably look at the design of your program and try to split the query into a lookup against one column at most from the application side, e.g.:
SELECT * FROM cong WHERE $term rLIKE upper(NAME)
There error is here:
$query .= " WHERE state rLIKE
(SELECT id FROM states WHERE upper(name) rLIKE '{$term}')";
$query .= " OR lga rLIKE
(SELECT id FROM local_govt WHERE upper(name) rLIKE '{$term}')";
rlike is a regex, but in the end boils down to a straight comparison of values. Your subqueries are returning multiple rows, so in a re-writen fashion, your query would be something more like:
WHERE state = a,b,c,...
OR lga = z,y,x,...
You're trying to do an equality test against multiple values, which is confusing the database. Equality tests are for SINGLE values, e.g. a=b, not a=b,c.

SQL ERROR When i join 2 tables

Sorry let me revise. I have a three tables:
events_year
• EventID
• YearID
• id
Date
• YearID
• Year
Event
• EventID
• EventName
• EventType
i want to dispay a record from the three tables like so:
EventName - Year: Marathon - 2008
i linked it to a table called "members" which contains a ID number field (members-id)
so i can limit the results to members id = $un(which is a username from a session)
I need to join the three tables and limit the results to the specific ID number record
Here is my portion of the code:
$query = "SELECT * FROM members JOIN events_year ON members.id = events_year.id ";
"SELECT * FROM Event JOIN events_year ON Event.EventID = events_year.EventID WHERE username = '$un'";
"SELECT * FROM Date JOIN events_year ON Date.YearID = events_year.YearID WHERE username = '$un'";
$results = mysql_query($query)
or die(mysql_error());
while ($row = mysql_fetch_array($results)) {
echo $row['Year'];
echo " - ";
echo $row['Event'];
echo "<br>";
}
the notices are almost self-explaining. There are no 'Year' and 'EventName' fields in the resultset. It's difficult (or: impossible) to tell why this happens as you haven't given your table-structure, but i guess this: 'Year' is a field of the date-table, 'EventName' is a field of the event-table - you're only selecting from members so this fields don't occur.
I don't understand why there are three sql-statements but only one is assigned to a variable - the other two are just standing there and do nothing. Please explain this and put more information into your question about what you're trying to achive, what your table-structure looks like and whats your expected result.
I think what you really wanted to do is some kind of joined query, so please take a look at the documentation to see how this works.
finally, i think your query should look like this:
SELECT
*
FROM
members
INNER JOIN
events_year ON members.id = events_year.id
INNER JOIN
Event ON Event.EventID = events_year.EventID
INNER JOIN
´Date´ ON ´Date´.YearID = events_year.YearID
WHERE
members.username = '$un'
Does the field 'Year' exist in the query output ? I suspect not.
the string $query is only using the first line of text:
"SELECT * FROM members JOIN events_year ON members.id = events_year.id ";
and not the others.
The query itself is not returning any fields that are called Year or EventName.
Do a var_dump($row) to find out what is being returned.

Help construct a simple query Using 3 tables

Hey guys need some more help
I have 3 tables USERS, PROFILEINTERESTS and INTERESTS
profile interests has the two foreign keys which link users and interests, they are just done by ID.
I have this so far
$statement = "SELECT
InterestID
FROM
`ProfileInterests`
WHERE
userID = '$profile'";
Now I want it so that it selects from Interests where what it gets from that query is the result.
So say that gives out 3 numbers
1
3
4
I want it to search the Interests table where ID is = to those...I just don't know how to physically write it in PHP...
Please help.
Using a JOIN:
Best option if you need values from the PROFILEINTERESTS table.
SELECT DISTINCT i.*
FROM INTERESTS i
JOIN PROFILEINTERESTS pi ON pi.interests_id = i.interests_id
WHERE pi.userid = $profileid
Using EXISTS:
SELECT i.*
FROM INTERESTS i
WHERE EXISTS (SELECT NULL
FROM PROFILEINTERESTS pi
WHERE pi.interests_id = i.interests_id
AND pi.userid = $profileid)
Using IN:
SELECT i.*
FROM INTERESTS i
WHERE i.interests_id IN (SELECT pi.interests_id
FROM PROFILEINTERESTS pi
WHERE pi.userid = $profileid)
You are on the right track, lets say you execute the query above using this PHP code:
$statement = mysql_query("SELECT InterestID FROM `ProfileInterests`
WHERE userID = '$profile'");
Then you can use a PHP loop to dynamically generate an SQL statement that will pull the desired IDs from a second table. So, for example, continuing the code above:
$SQL = "";
while ($statementLoop = mysql_fetch_assoc($statement)) {
//Note the extra space on the end of the query
$SQL .= "`id` = '{$statementLoop['InterestID']}' OR ";
}
//Trim the " OR " off the end of the query
$SQL = rtrim($SQL, " OR ");
//Now run the dynamic SQL, using the query generated above
$query = mysql_query("SELECT * FROM `table2` WHERE {$SQL}")
I haven't tested the code, but it should work. So, this code will generate SQL like this:
SELECT * FROM `table2` WHERE `id` = '1' OR `id` = '3' OR `id` = '4'
Hope that helps,
spryno724
Most likely you want to join the tables
select
i.Name
from
ProfileInterests p
inner join
interests i
on
p.interestid = i.interestid
where
p.userid = 1

Categories