MySQL query to select specific data - php

I would like to display the data that belongs to any of my users when they login to the site, as well as the name of each table (they completed offers on them).
This is the code I used, but when I add it it's not working.
$result = mysql_query('SELECT *,\'tbl1\' AS tablename FROM (SELECT * FROM table1 WHERE user_id='$user_id') as tbl1 UNION SELECT *,\'tbl2\' AS tablename FROM (SELECT * FROM table1 WHERE user_id='$user_id') as tbl2'. ' ORDER BY `date` DESC');
while($sdata = mysql_fetch_array($result)){
echo $sdata['date'];
echo $sdata['tablename'];
echo $sdata['user_reward'];
}
Where did I make a mistake?

You are missing the concatenation operators here, around $user_id:
$result = mysql_query(
'SELECT *,\'tbl1\' AS tablename FROM (
SELECT * FROM table1 WHERE user_id=' . $user_id . '
) as tbl1
UNION
SELECT *,\'tbl2\' AS tablename FROM (
SELECT * FROM table1 WHERE user_id=' . $user_id . '
) as tbl2' . ' ORDER BY `date` DESC'
);
I've wrapped the call for more clarity - I suggest you do the same in your own code. I'd be inclined to use " marks here instead, so you don't need to escape apostrophes.
The ORDER BY clause seems to be redundantly concatenated as well - remove the dot and add this part of the query to the as tbl2 part.
Here's how I would do it:
$sql = "
SELECT *, 'tbl1' AS tablename FROM (
SELECT * FROM table1 WHERE user_id={$user_id}
) as tbl1
UNION
SELECT *, 'tbl2' AS tablename FROM (
SELECT * FROM table1 WHERE user_id={$user_id}
) as tbl2
ORDER BY `date` DESC
";
$result = mysql_query($sql);
Make sure that $user_id is properly escaped or cast, to avoid security problems. Also, this database library is no longer recommended, and will be removed in a future version of PHP. It would be better to move to PDO or mysqli, and use parameterisation.
Finally, it does rather look like the query itself is rather cumbersome - it looks like it could be simplified. Perhaps ask a separate question on that?

Related

SQL UNION 2 SELECT on same table

I have 2 SELECT on the same table "contratto"; in php (and mysql) I do it as:
$sql_1=" SELECT * FROM contratto WHERE id_cliente='2' " ;
$sql_2=" SELECT * FROM contratto JOIN cliente ON contratto.id_cliente=cliente.id WHERE cliente.id_rivenditore = '2' " ;
$sql= "(" . $sql_1 . ") UNION ALL (" . $sql_2 .") ; ";
mysqli_query($connect, $sql);
while($row = mysqli_fetch_assoc($risultato_query)) { ..... }
The 2 SQL query $sql_1 and $sql_2 separately work fine.
The query $sql (union of $sql_1 and $sql_2) doesn't work, that is:
( SELECT * FROM contratto WHERE id_cliente=’2′ ) UNION ALL ( SELECT * FROM contratto JOIN cliente ON contratto.id_cliente=cliente.id WHERE cliente.id_rivenditore = ‘2’ ) ;
I get the error "mysqli_fetch_assoc() expects parameter 1 to be mysqli_result, boolean given in ..."
What is wrong?
At least one error is coming from the union. All subqueries in the union need to have the same columns, so select * is not appropriate (especially in this case).
Another error comes from PHP, because you are not checking for errors from SQL. If you did, you would see the error message from the database.

Add 2 row counts together in MySql

I am adapting something and I need to add 2 row counts together in mysql. So far I have
<?
$result = mysql_query("SELECT * FROM Table1 WHERE Field1 ='2' ");
$num_rows = mysql_num_rows($result);
$result2 = mysql_query("SELECT * FROM Table2 WHERE Field2 ='6' ");
$num_rows2 = mysql_num_rows($result2);
$num_rows3 = ($num_rows + $num_rows2)
echo "$num_rows3";
?>
I can echo either $num_rows OR $num_rows2 fine but I need to do the calculation then echo $num_rows3.
I am probably doing something stupid here but I do not know mysql at all so I am trying to learn.
Thanks for the help!
You could also have one single query for both counts:
SELECT count(t1.id), count(t2.id)
FROM (SELECT id FROM Table1 WHERE Field1 ='2') t1,
(SELECT id FROM Table2 WHERE Field2 ='6') t2
Also note that you are missing a ; when summing the counts.
This is just a suggestion even though you got your answer.
If you want to add those into ONE MYSQLI query you could use this:
SELECT sum(cnt) from
(SELECT COUNT(*) cnt FROM T1 WHERE Field1=2 union all
SELECT COUNT(*) cnt FROM T2 WHERE Field2=6) a
I just don't see the point in fetching all data in SELECT * FROM Where all you do is mysql_num_rows($result)
Hope this helps, and maybe improves your code.
Good Luck!
Here is just a demo IN SQLFiddle, so you can see this in action:
SQLFiddle Demo
I was missing the ; after the calculation!!
Using only one query and counting before add, a possible code is
<?
$query = "SELECT c1 + c2 FROM ";
$query .= "(SELECT count(Field1) c1 FROM Table1 WHERE Field1 ='2') t1,";
$query .= "(SELECT count(Field2) c2 FROM Table2 WHERE Field2 ='6') t2";
$result = mysql_query($query);
$value = mysql_num_rows($result);
echo "$value";
?>

mysql select union doesn't work

Mysql version 5.1.
Code example:
mysql_query("SELECT * FROM abonents WHERE `session_id`='$current_sess_id' UNION SELECT * FROM abonents_problem WHERE `session_id`='$current_sess_id' UNION SELECT * FROM abonents_stop WHERE `session_id`='$current_sess_id'");
Runs if remove "UNION", example:
mysql_query("SELECT * FROM abonents WHERE `session_id`='$current_sess_id'" );
"WTF Code" forever =):
$rez_11_one = mysql_query(
"SELECT * FROM abonents WHERE `session_id`='$current_sess_id'"
);
$rez_11_two = mysql_query(
"SELECT * FROM abonents_problem WHERE `session_id`='$current_sess_id'"
);
$rez_11_three = mysql_query(
"SELECT * FROM abonents_stop WHERE `session_id`='$current_sess_id'"
);
if ($rez_11_one) {
$rez_11 = $rez_11_one;
} elseif ($rez_11_two) {
$rez_11 = $rez_11_two;
} else {
$rez_11 = $rez_11_three;
}
Thank's for help
reference to the mysql documentation UNION only works if all querys return the same number of columns.
http://dev.mysql.com/doc/refman/4.1/en/union.html
therefore as you use a selector asterisks * i think the tables have a different amount of columns. use select eg
SELECT 1,2 FROM foo UNION SELECT 1,2 FROM bar
to get per query the same amount of columns.
Try query without "*"
Like this
mysql_query("SELECT <table_column_name> FROM abonents WHERE `session_id`='$current_sess_id' UNION SELECT <table_column_name> FROM abonents_problem WHERE `session_id`='$current_sess_id' UNION SELECT <table_column_name> FROM abonents_stop WHERE `session_id`='$current_sess_id'");
You may need to add escape characters to the string to make it:
mysql_query("SELECT * FROM abonents WHERE \`session_id\`=\'$current_sess_id\' UNION SELECT * FROM abonents_problem WHERE \`session_id\`=\'$current_sess_id\' UNION SELECT * FROM abonents_stop WHERE \`session_id\`=\'$current_sess_id\'");
Make sure if the query returns the same number of columns..According to the documentation of UNION.It only works if the query returns same number of columns

How can I convert these two queries in a loop into a single JOINed query?

I am currently trying to get data from my table (mostKills by Weapon in a table with over 300 kills). Initially I did a normal query
$q = $mysql->query("SELECT * FROM `kills`") or die($mysql->error);
but when I tried to
$query2 = $mysql->query("SELECT `killerID`, COUNT(`killerID`) AS tot_kills FROM `kills` WHERE `killText` LIKE '%$gun%' GROUP BY `killerID` ORDER BY `tot_kills` DESC;") or die($mysql->error);
$kData = $query2->fetch_assoc();
$query3 = $mysql->query("SELECT `Username` FROM `players` WHERE `ID` = '" . $kData['killerID'] . "'") or die($mysql->error);
$uData = $query3->fetch_assoc();
$array[$gun]['Kills']++;
$array[$gun]['Gun'] = $gun;
$array[$gun]['BestKiller'] = $uData['Username'];
$array[$gun]['killAmount'] = $kData['tot_kills'];
function sortByKills($a, $b) {
return $b['Kills'] - $a['Kills'];
}
usort($array, 'sortByKills');
foreach($array as $i => $value)
{
// table here
}
I had to do it in a while loop, which caused there to be around 600 queries, and that is obviously not acceptable. Do you have any tips on how I can optimize this, or even turn this into a single query?
I heared JOIN is good for this, but I don't know much about it, and was wondering if you guys could help me
Try this...
I added a inner join and added a username to your select clause. The MIN() is just a way to include the username column in the select and will not have an impact on you result as long as you have just 1 username for every Killerid
SELECT `killerID`
, COUNT(`killerID`) AS tot_kills
, MIN(`Username`) AS username
FROM `kills`
INNER JOIN `players`
ON `players`.`id` = `kills`.`killerid`
WHERE `killText` LIKE '%$gun%'
GROUP BY `killerID`
ORDER BY `tot_kills` DESC
SELECT kills.killerID, count(kills.killerID) as killTotal, players.Username
FROM kills, players
WHERE kills.killText
LIKE '%$gun%'
AND players.ID` = kills.killerID
GROUP BY kills.killerID
ORDER BY kills.tot_kills DESC
Here is a good place to learn some more about joins.
http://www.sitepoint.com/understanding-sql-joins-mysql-database/
The best way is to have your own knowledge so you can be able to tune up your select queries.
Also put more indexes to your DB, and try to search and join by index.

Query inside of another query?

I've searched and found ways to do queries inside queries, but I have not found the right answer.
What I am trying to do is to fetch comments from the table called users_profiles_comments and by doing that I will get the field of '.$member["author"].'. Then I want to show who made the comment with their rank and a display picture.
But because there is no user details stored in the comments table because its for comments, I need to create a query inside of my query result where I can have this:
"SELECT * FROM users WHERE username = $member['author'] ORDER BY `id` ASC"
The '.$member["author"].' value comes from the main query but I need it so it can find fields in my users table.
$sql = "SELECT * FROM users_profiles_comments WHERE postid = '1' ORDER BY `id` ASC";
$stm = $dbh->prepare($sql);
$stm->execute();
$users = $stm->fetchAll();
foreach ($users as $row) {
print '
<img src="'.$member["profilepic"].'" style="float:left;margin-right:10px;" width="80px" height="85pxm">
<h4>'. $row["author"] .'
<small>'. $row["date"] .'</small>
</h4>
<p>'. $row["content"] .'</p><hr> </a></li>';
}
echo '
</div>
';
I hope you understand.
Edit:
The database.
users Table
http://img855.imageshack.us/img855/4387/qyjl.png
users_profiles_comments table
http://i.imgur.com/aKRF5MN.png
But because there is no user details stored in the comments table because its for comments
This is good. You do not want to have your database information duplicated in both tables (de-normalized data) - there is no need.
Generally a foreign key is added to inverse side of the relationship. This would mean you have a user_id column within your comments table, allowing you to select the data in one query using a JOIN
SELECT comment.*, user.name AS comment_author
FROM comment
INNER JOIN user ON user.id = comment.user_id
WHERE user.id = 123
Edit - I flipped to JOIN to return comments rather than users, (as you said "to fetch comments") however both ways will work, it just depends which side of the relationship you are on.
Edit 2 To respond to your comment;
How would I be able to show this on my PHP code on the result?
you can be more specific with the above query (not use *) and render it as follows :
$sql = "
SELECT
comment.`date` as comment_date,
comment.content,
user.name AS author_name,
user.profilepic as author_pic
FROM
users_profiles_comments as comment
INNER JOIN
user ON user.id = comment.user_id
WHERE
comment.postid = 1
";
//...
$comments = $stmt->fetchAll();
foreach ($comments as $comment) {
echo '<img src="' . $comment['author_pic'] . '"/>';
echo '<h4>' . $comment['author_name'] . '<small>' . $comment['comment_date'] .'</small></h4>';
echo '<p>' . $comment['content'] . '</p>';
}
You can select member name in SQL statement. You can try this query, this query will bring all the information from two table if users.username = users_profiles_comments.author
WAY 1:
SELECT t1.*, t2.* FROM
(
SELECT * FROM users WHERE username = '.$member["author"].' ORDER BY `id` ASC
) AS t1
LEFT JOIN
(
SELECT * FROM users_profiles_comments WHERE postid = '1' ORDER BY `id` ASC
) AS t2
ON t1.username = t2.author
Finally, do your foreach to print
===================================================================
WAY 2:
You can try this also-
SELECT *,
(SELECT profilepic FROM users WHERE users.username = users_profiles_comments.author) AS profilepic
FROM users_profiles_comments WHERE postid = '1' ORDER BY `id` ASC
And print profilepic using $row['profilepic'] in your foreach loop
=====================================================================
WAY 3:
SELECT t1.*, t2.* FROM
(
SELECT * FROM comments WHERE postid = '1'
) AS t1
LEFT JOIN
(
SELECT * FROM users
) AS t2
ON t1.author = t2.username
What I understand is that you need to get information about the user from another table called user_profile_comments, based on the user id (correct me if wrong: :-)). Use a left outer JOIN to fetch data from another table, limited on user id.
See http://www.w3schools.com/sql/sql_join.asp for more info.

Categories