我可以在同一个查询中连接表并使用AVG

时间:2011-06-17 21:18:09

标签: php mysql

我是php和MySQL的新手,我在尝试解决这个问题时遇到了问题。

我有这个查询

SELECT * FROM comments, supps 
WHERE supps.tutorialid = comments.tutorialid 
  AND category='1' 
ORDER BY $orderby $sort 
LIMIT $startrow, $limit

哪个工作正常,但问题是我还要在评论表中包含列的AVG,而我似乎无法使用此查询。任何人都可以帮助我

3 个答案:

答案 0 :(得分:1)

要使用聚合函数,您需要使用'GROUP BY'子句。通常在'ORDER BY'之前。注意:如果要使用group by,则需要在SELECT子句中定义属性,否则事情会变得有点粘。

例如:

SELECT id, avg(value) FROM comments c
INNER JOIN supps s
    on c.tutorialid = s.tutorialid
WHERE category = 1
GROUP BY id
etc...

答案 1 :(得分:0)

是的,有可能。请查看SQL Wikibooks tutorial上的示例,其中列出了在两个不同表格中使用AVG()的以下示例:

/* Without INNER JOIN */
 SELECT AVG(Price), Manufacturers.Name
   FROM Products, Manufacturers
   WHERE Products.Manufacturer = Manufacturers.Code
   GROUP BY Manufacturers.Name;

 /* With INNER JOIN */
 SELECT AVG(Price), Manufacturers.Name
   FROM Products INNER JOIN Manufacturers
   ON Products.Manufacturer = Manufacturers.Code
   GROUP BY Manufacturers.Name;

答案 2 :(得分:0)

隐式SQL加入被认为是有害的
首先请不要使用隐式连接语法。它属于1989年,请把它埋葬在那里。

看起来你有一个SQL注入泄漏
如果你使用php并且你没有将注入的变量放在单引号中' mysql_real_escape_string()将不起作用!

你将成为at risk of SQL-injection

最后,您要在查询中注入列名。这样做时mysql_real_escape_string()不会保护您,也不会使用PDO或其他任何东西。您需要针对预先提交的白名单检查列名称,以免成为SQL注入攻击的受害者。 See here for more info:
如果将$ vars注入限制子句mysql_real_escape_string()不起作用,因为MySQL不会将这些视为值,而是作为文字,您需要将它们转换为整数以使其安全。

将查询重写到PHP代码中并在其前面执行:

//stricly speaking not needed here, because we only accept integers
//but I would use them anyway, just in case you change the query and the
//role of these vars change.
$limit = mysql_real_escape_string($_POST['limit']);
$startrow = mysql_real_escape_string($_POST['startrow']);

//Check injected column, table and database names against a whitelist!
$allowed_columns = array('column1', 'column2');
$orderby = $_POST['orderby'];
$sort = $_POST['sort'];
if !(in_array($orderby, $allowed_columns)) {die ("no way Jose");}
if !(in_array($sort, $allowed_columns)) {die ("no way Jose");}

//Make 100% sure injected limit parameters are integers.
if !((int) $startrow == $startrow) {die ("no way Jose");}
if !((int) $limit == $limit) {die ("no way Jose");}

$query = "SELECT s.*, c.* ,AVG(c.field1) as average 
          FROM comments c
          INNER JOIN supps s ON (s.tutorialid = c.tutorialid)
          WHERE category = '1'
          GROUP BY s.id 
          ORDER BY `$orderby`, `$sort`  //surround injected column names with ` 
          LIMIT '$startrow', '$limit' ";

SQL注入保护概述
1.始终使用mysql_real_escape_string()来转义来自外部的数据。 (甚至更好地使用PDO)
2.使用'单引号在您的查询中为Surround注入$ var值;如果您没有使用mysql_real_escape_string()转义工作。
3.根据白名单检查注入的表,列和数据库名称 4.环绕$ vars用于反引号`中的表,列和数据库名称;这不是一个安全措施,但如果你使用保留字,(颤抖)字段名称和空格,你的查询将失败,反引号修复此问题。
5.测试你的限制条款中注入$ vars是否为整数。

没有做任何这些事情,你的服务器将被计划!。

回到你的问题
我的手指受伤了,但其他人也很友好地回答了你的问题。

<强>链接
一般的SQL注入:How does the SQL injection from the "Bobby Tables" XKCD comic work?
注入列名称的白名单:How to prevent SQL injection with dynamic tablenames?