Why doesn't this SQL command work? - mysql

I cannot figure out why this sql query isn't working and why it doesn't filter by the keyword coming from URL.
Here is my code:
include("menujednoty.php");
$hostname="localhost";
$username="kintrogorgo";
$password="password";
$keyword = $_GET['a.tovar'];
$db = "jednoty";
$dbh = new PDO("mysql:host=$hostname;dbname=$db", $username, $password);
foreach($dbh->query ('SELECT a.tovar ,
( select sum(b.kusy) from jednotypredaj as b where b.tovar=a.tovar and b.co="prijem" ) as prijem_ks,
( select sum(c.kusy) from jednotypredaj as c where c.tovar=a.tovar and c.co="predaj" ) as predaj_ks, kod
FROM jednotypredaj WHERE
(a.tovar LIKE '%$keyword%' ) as a GROUP BY a.tovar ORDER by a.tovar ASC') as $row)
{
echo "<tr>";
echo "<td>" . $row['tovar'] . "</td>";
echo "<td>" . $row['prijem_ks']. "</td>"; //Tu by mali bit predane kusy
echo "<td>" . $row['predaj_ks'] . "</td>";
echo "<td>" . $row['kod'] . "</td>";
echo "<td>" . ($row['predaj_ks']-$row['prijem_ks'] . "</td>");
echo "<td>" . (100/$row['prijem_ks']*$row['predaj_ks'] . "</td>");
echo '<td>ZobraziƄ</td>';
//echo '<td>In Development</td>';
//echo '<td>In Development 2</td>';

The quotes are breaking the SQL syntax, rewrite as a prepared statement to make it easier:
$stmt = $dbh->prepare('SELECT a.tovar ,
( select sum(b.kusy) from jednotypredaj as b
where b.tovar=a.tovar and b.co=:received ) as prijem_ks,
( select sum(c.kusy) from jednotypredaj as c
where c.tovar=a.tovar and c.co=:paid ) as predaj_ks, kod
FROM jednotypredaj WHERE
(a.tovar LIKE :keyword ) as a
GROUP BY a.tovar ORDER by a.tovar ASC');
$stmt->execute(array('received' => 'prijem','paid' => 'predaj','keyword' => $keyword));
foreach ($stmt as $row) {
echo "<tr>";
echo "<td>" . $row['tovar'] . "</td>";
...

Reconsider your SQL statement as you can either run correlated subqueries or conditional aggregates. Also, you table alias, a, was incorrectly positioned after WHERE clause:
Correlated subqueries (retains unit level records with kod column)
SELECT a.tovar,
(select sum(b.kusy) from jednotypredaj as b
where b.tovar=a.tovar and b.co='prijem') as prijem_ks,
(select sum(c.kusy) from jednotypredaj as c
where c.tovar=a.tovar and c.co='predaj') as predaj_ks,
a.kod
FROM jednotypredaj as a
WHERE (a.tovar LIKE '%$keyword%')
ORDER by a.tovar ASC
Conditional aggregates (group by aggregate records w/o kod unless added as a group)
SELECT a.tovar,
SUM(CASE WHEN a.co='prijem' THEN a.kusy ELSE NULL END) as prijem_ks,
SUM(CASE WHEN a.co='predaj' THEN a.kusy ELSE NULL END) as predaj_ks
FROM jednotypredaj as a
WHERE (a.tovar LIKE '%$keyword%')
GROUP BY a.tovar
ORDER by a.tovar ASC
MySQL may allow kod in SELECT clause and not in GROUP BY clause of aggregate query if your instance has the ONLY_FULL_GROUP_BY setting turned off but is not recommended and not ANSI-SQL compliant.
And as mentioned parameterize these queries in PHP script, binding string literals, that helps avoid quote handling and SQL injection.

Related

how to fetch with an AM/PM time_format from any database

I want to fetch data with AM/PM format, but before that, i need to choose a database to make this.
$event_name='database_name';
I also using INNER JOIN .
Can anybody know how to format time in this case?
$event_name='database name';
$conn = mysqli_connect($servername, $username, $password);
if (!$conn) {
die("Connection failed: " . mysqli_connect_error());}
$sql = "SELECT $event_name.student_login.LOG_IN, $event_name.student_login.TIME_FORMAT(LOG_IN,"%r"), event_attendance.student_data.* FROM event_attendance.student_data
inner JOIN $event_name.student_login ON $event_name.student_login.SERIAL = event_attendance.student_data.SERIAL order by $event_name.student_login.LOG_IN DESC";
//using (SERIAL)
$result = mysqli_query($conn, $sql);
$i = 1;
if (mysqli_num_rows($result) > 0) {
// output data of each row
while($row = mysqli_fetch_assoc($result)) {
echo "<td width='2'><center><B>".$i; $i++; echo"</B></center></td>";
echo "<td>" . $row["ID"]."</td>";
echo "<td>" . $row["LASTNAME"].", ". $row["FIRSTNAME"]." ". $row["MIDDLENAME"]."."."</td>";
echo "<td><center>" . $row["COURSE"]."</center></td>";
echo "<td><center>" . $row["YEAR"]."</center></td>";
echo "<td><center>" . $row["LOG_IN"] ."</center></td>";
echo "<td><center>" . $row["DATE"]."</center></td><tr>";
}
}
my code didn't work with this.
$event_name.student_login.TIME_FORMAT(LOG_IN,"%r")
TIME_FORMAT is an in-built MYSQL function and not a function of the table $event_name.student_login so using $event_name.student_login.TIME_FORMAT(LOG_IN,"%r") is wrong
Secondly, your query is in double quotes so you cannot directly use another double quote in the query string. So you need to change $event_name.student_login.TIME_FORMAT(LOG_IN,"%r") to TIME_FORMAT($event_name.student_login.LOG_IN, '%r')
Try this
$sql = "SELECT $event_name.student_login.LOG_IN, TIME_FORMAT($event_name.student_login.LOG_IN, '%r'), event_attendance.student_data.* FROM event_attendance.student_data inner JOIN $event_name.student_login ON $event_name.student_login.SERIAL = event_attendance.student_data.SERIAL order by $event_name.student_login.LOG_IN DESC";
or the cleaner version using alias
$sql = "SELECT sl.LOG_IN, TIME_FORMAT(sl.LOG_IN, '%r'), sd.* FROM event_attendance.student_data sd inner JOIN $event_name.student_login sl ON sl.SERIAL = sd.SERIAL order by sl.LOG_IN DESC";

SQl code analysis

Please i need help to analyze this code . I am bit confuse to interpret what it means . This is not a code i write but some else .
All i need to do is to understand it and able to implement it
somewhere else . Thank you
$sql = "select t0.userid,concat(t3.firstname,',',t3.lastname) as name,count(*) as quizs,sum(if(t0.finalgrade > 0,1,0)) as quiz, sum(t0.finalgrade) as grade";
$sql .= " from mdl_grade_grades t0";
$sql .= " left join mdl_grade_items t1 on( t0.itemid= t1.id and t1.courseid = 37 and (t1.itemname like '%Daily Quiz%' or t1.itemname in ('Mid Term Exam','FINAL EXAM')))";
$sql .= " left join mdl_user t3 on(t3.id=t0.userid)";
$sql .= " where t0.userid >= 480";
$sql .= " group by t3.firstname,t3.lastname";
$res = mysql_query($sql);
$response->totalcount = mysql_num_rows($res);
$sql .= " Order by t3.firstname,t3.lastname";
$sql .= " Limit " .$start ."," .$limit ;
$res = mysql_query($sql);
while ($row = mysql_fetch_object($res)){
$attend = $row->gquiz / $row->quizs;
$grade = $row->grade / $row->gquiz;
$response->items[] = array('id' => $row->userid,'name' => $row->name,'attend' => $attend,'grade' => $grade);
}
//
echo json_encode($response);
The function sum(if(t0.finalgrade > 0,1,0)) actually counts the number of records having a finalgrade greater than 0.
The function sum(t0.finalgrade) simply sums the finalgrade of all records.
IF() is a builtin function and it's documented:
IF(expr1,expr2,expr3)
If expr1 is TRUE (expr1 <> 0 and expr1 <> NULL), IF() returns expr2.
Otherwise, it returns expr3.
In your case:
if(t0.finalgrade > 0,1,0)
If final grade is greater than 0 then return 1, else return 0.
Finally, SUM() sums all these zeros and ones.
PHP code does not play any role in this MySQL logic.

Displaying Foreign Key data in MySQL

I have a BusinessID in both my staff and business table and I'm wanting to display the staff members for everyone in a particular business. The query below gives me this error.
ERROR: Could not able to execute SELECT * FROM business b inner join BusinessID b ON b.BusinessID = s.BusinessID WHERE b.BusinessID = 1. Not unique table/alias: 'b'
This is my foreign key file
<html>
<body>
<?php
include_once("connect.php");
$BusinessID = $_GET['BusinessID'];
$sql= "SELECT *
FROM business b
inner join BusinessID b
ON b.BusinessID = s.BusinessID
WHERE b.BusinessID = $BusinessID";
if($result = $conn->query($sql)){
if($result->num_rows > 0){
echo "<table>";
echo "<tr>";
echo "<th>Name</th>";
echo "<th>BusinessID<th>";
echo "</tr>";
while($row = $result->fetch_array()){
echo "<tr>";
echo "<td>" . $row['Name'] . "</td>";
echo "<td>" . $row['BusinessID'] . "</td>";
echo "</tr>";
}
echo "</table>";
// Free result set
$result->free();
} else{
echo "No records matching your query were found.";
}
} else{
echo "ERROR: Could not able to execute $sql. " . $conn->error;
}
// Close connection
$conn->close();
?>
</body>
</html>
Below is the fix
$sql= "SELECT *
FROM staff
WHERE BusinessID = $BusinessID";
You need to use a join statement
Select *
From staff as S
Join business as B
on s.businessID=b.businessID
--Where clause <--- If you want to filter by anything.
You say you "have a BusinessID". If it were in $BusinessID, the form of query you want seems to be:
query select * from staff where s.BusinessID = $BusinessID
However be warned of SQL code injection as addressed at How can I prevent SQL injection in PHP? (See also the coincidental meta post from today Should the answer be the simplest ever possible, even at the expense of quality/security?) The correct way to deal with this in a PHP context is to query via prepared statements.

mysql - combining columns and tables

I have a site where I have a database for all accounts and whatnot, and another for storing actions that the user has done on the site.
Each user has their own table but I want to combine the data of each user group (all users that are "linked together") and order that data in the time the actions took place.
Here's what I have;
<?php
$query = "SELECT `TALKING_TO` FROM `nnn_instant_messaging` WHERE `AUTHOR` = '" . DISPLAY_NAME . "' AND `TALKING_TO` != ''";
$query = mysql_query( $query, $CON ) or die( "_error_ " . mysql_error());
if( mysql_num_rows( $query ) != 0 ) {
$table_str = "";
$select_ref_clause = "( ";
$select_time_stamp_clause = "( ";
while( $row = mysql_fetch_array( $query ) ) {
$table_str .= "`actvbiz_networks`.`" . $row['TALKING_TO'] . "`, ";
$select_ref_clause .= "`actvbiz_networks`.`" . $row['TALKING_TO'] . ".REF`, ";
$select_time_stamp_clause .= "`actvbiz_networks`.`" . $row['TALKING_TO'] . ".TIME_STAMP`, ";
}
$table_str = $table_str . "`actvbiz_networks`.`" . DISPLAY_NAME . "`";
$select_ref_clause = substr($select_ref_clause, 0, -2) . ") AS `REF`, ";
$select_time_stamp_clause = substr($select_time_stamp_clause, 0, -2) . " ) AS `TIME_STAMP`";
}else{
$table_str = "`actvbiz_networks`.`" . DISPLAY_NAME . "`";
$select_ref_clause = "`REF`, ";
$select_time_stamp_clause = "`TIME_STAMP`";
}
$where_clause = $select_ref_clause . $select_time_stamp_clause;
$query = "SELECT " . $where_clause . " FROM " . $table_str . " ORDER BY TIME_STAMP";
die($query);
$query = mysql_query( $query, $CON ) or die( "_error_ " . mysql_error());
if( mysql_num_rows( $query ) != 0 ) {
}else{
?>
<p>Currently no actions have taken place in your network.</p>
<?php
}
?>
The code above returns the sql statement:
SELECT ( `actvbiz_networks`.`john_doe.REF`, `actvbiz_networks`.`Emmalene_Jackson.REF`) AS `REF`, ( `actvbiz_networks`.`john_doe.TIME_STAMP`, `actvbiz_networks`.`Emmalene_Jackson.TIME_STAMP` ) AS `TIME_STAMP` FROM `actvbiz_networks`.`john_doe`, `actvbiz_networks`.`Emmalene_Jackson`, `actvbiz_networks`.`act_web_designs` ORDER BY TIME_STAMP
I really am learning on my feet with SQL.
Its not the PHP I have a problem with (I can quite happily code away with PHP); It's just help with the SQL statement.
Any help much appreciated.
Didn't take the time to through your code, but from the question it sounds like you want UNION.
SELECT
3 AS a
UNION SELECT
2 AS a
UNION SELECT
1 AS a
ORDER BY a
Gives
a
=
1
2
3
EDIT: So perhaps something like this?
DROP TEMPORARY TABLE IF EXISTS t1;
DROP TEMPORARY TABLE IF EXISTS t2;
DROP TEMPORARY TABLE IF EXISTS tmp;
CREATE TEMPORARY TABLE t1 (
a INT(11)
);
CREATE TEMPORARY TABLE t2 (
b INT(11)
);
INSERT INTO t1 VALUES (1), (2), (3);
INSERT INTO t2 VALUES (4), (5), (6);
CREATE TEMPORARY TABLE tmp
SELECT
b AS f
FROM t2
UNION SELECT
a AS f
FROM t1
ORDER BY f;
SELECT * FROM tmp;
returns
f
=
1
2
3
4
5
6
Have you tried using a view? This way, you can use the UNION as simendsjo suggested and everything is in a single table. This is not exactly a temporary solution but a very nice, clean and efficient way of doing this.
I endeed up solving by using simendsjo's tips and used UNION ALL
<?php
$query = "SELECT `TALKING_TO` FROM `nnn_instant_messaging` WHERE `AUTHOR` = '" . DISPLAY_NAME . "' AND `TALKING_TO` != ''";
$query = mysql_query( $query, $CON ) or die( "_error_ " . mysql_error());
if( mysql_num_rows( $query ) != 0 ) {
while( $row = mysql_fetch_array( $query ) ) {
$table_str = 'SELECT REF, ACTION, TIME_STAMP, DATA, IMAGE, DISPLAY_NAME FROM actvbiz_networks.' . $row['TALKING_TO'] . ' UNION ALL ';
}
}else{
$table_str = "";
}
$table_str = $table_str . 'SELECT REF, ACTION, TIME_STAMP, DATA, IMAGE, DISPLAY_NAME FROM actvbiz_networks.' . DISPLAY_NAME . ' ORDER BY TIME_STAMP DESC';
$query = mysql_query( $table_str, $CON ) or die( "_error_ " . mysql_error());
if( mysql_num_rows( $query ) != 0 ) {
while( $rows = mysql_fetch_array( $query ) ) {

MySQL MAX_JOIN_SIZE errors

I am asking this question on behalf of a small group of my users that have this problem.
Once the script they are using gets to the 21st ID, it generates the following error:
The SELECT would examine more than
MAX_JOIN_SIZE rows; check your WHERE
and use SET SQL_BIG_SELECTS=1 or SET
SQL_MAX_JOIN_SIZE=# if the SELECT is
okay
I have researched this as much as possible and found something of an answer : http://dev.mysql.com/doc/refman/5.0/en/set-option.html
The problem is that they are on shared hosting so they cannot change their MySQL settings to fix the errors.
Is there anything I can write into my script so that they do not have this problem?
This is the function that generates the database query based on which modules are loaded:
$sql = 'SELECT a.id as id , a.address as address';
$query = 'SELECT'
. ' name AS module_name'
. ', databasename AS module_database'
. ', pregmatch AS module_pregmatch'
. ', pregmatch2 AS module_pregmatch2'
. ', html AS module_html'
. ', sqlselect AS database_sqlselect'
. ', sqljoin AS database_sqljoin'
. ', sqlupdatewithvalue AS database_sqlupdatewithvalue'
. ', sqlupdatenovalue AS database_sqlupdatenovalue'
. ' FROM #__aqsgmeta_modules'
. ' WHERE enabled = 1'
. ' ORDER BY id';
$db->setQuery($query);
$results = $db->loadObjectList();
if (count($results) != 0) {
foreach ($results as $result) {
$sqlselect .= ', ';
$sqlselect .= $result->database_sqlselect;
$sqljoin .= ' ';
$result->database_sqljoin = preg_replace('/\{DATABASENAME\}/Ui', $result->module_database, $result->database_sqljoin);
if (!(preg_match("/" . $result->database_sqljoin . "/Ui", $sqljoin)))
$sqljoin .= $result->database_sqljoin;
}
}
if ($use_sh404sef)
$sqlselect .= ', g.oldurl AS sefurl';
$sql .= $sqlselect;
$sql .= ' FROM #__aqsgmeta_address AS a';
$sql .= $sqljoin;
if ($use_sh404sef)
$sql .= ' LEFT JOIN #__redirection AS g ON g.newurl = a.address';
$sql .=
//. ' WHERE a.id IN (' . $cids . ')'
' WHERE a.id = ' . $id
. ' ORDER BY a.address asc,a.id '
;
$db->setQuery($sql);
$rows = $db->loadObjectList();
MAX_JOIN_SIZE is a safety catch commonly used on the shared hostings.
It won't let you accidentally run long queries which would hang the server.
Issue this command:
SET SQL_BIG_SELECTS = 1
before running the query you know to return lots of values.
The MAX_JOIN_SIZE gets hit when MySQL calculates the Cartesian product of a join, not the actual expected records back. Therefore, if you're joining a massive table to another massive table, this will creep up. Use indexes and views to pare down the possible table hits if it's really that large.
See more here: MySQL - SQL_BIG_SELECTS