mySQL句子的问题包括两个临时表创建

mySQL句子的问题包括两个临时表创建

问题描述:

I have a mySQL sentence that works like a charm if I execute it in my phpMyAdmin:

CREATE TEMPORARY TABLE hash1
      SELECT * FROM
      (
        (
            SELECT DISTINCT feature_id AS fl, feature_value AS fv FROM gf_product_features WHERE feature_id = '1' AND feature_value = 'No frost total'
        ) UNION 
        (
            SELECT DISTINCT feature_id AS fl, feature_value AS fv FROM gf_product_features WHERE feature_id = '3' AND feature_value = '43'
        )) AS q;


      CREATE TEMPORARY TABLE hash2
        SELECT * FROM hash1;

        SELECT 
          p.id AS id, 
          p.main_image AS main_image, 
          p.type AS taxonomy, 
          p.name AS model, 
          p.sku AS sku, 
          p.price AS price, 
          b.brand_name AS brand_name, 
          b.brand_image AS brand_logo,
          pf.feature_value AS feature_value, 
          f.feature AS feature_label,
          f.id AS feature_id
        FROM
        (
          SELECT  a.*
          FROM    gf_product AS a
          INNER JOIN
          (
            SELECT product_id
            FROM
            (
              SELECT a.product_id , count(*) AS commons
              FROM   gf_product_features AS a
              INNER JOIN hash1 AS b 
                ON    a.feature_id = b.fl 
                AND   a.feature_value = b.fv 
              GROUP BY a.product_id 
              ) AS features
              WHERE commons = (SELECT count(*) AS count FROM hash2)  
            ) b1 ON a.id = b1.product_id 
          ) AS p
        INNER JOIN  gf_brands AS b 
            ON p.brand_id = b.id
        INNER JOIN  gf_product_features AS pf 
            ON pf.product_id = p.id   
        INNER JOIN  gf_features AS f 
            ON pf.feature_id = f.id
        ORDER BY    price ASC, 
                    feature_id ASC

I want to execute a php function through Ajax request, that constructs dinamically the sql sentence above, but I'm always getting this error in my browser's console:

    You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CREATE TEMPORARY TABLE hash2
        SELECT * FROM hash1;

        SELECT 
       ' at line 12

And thus, the following error too:

Warning: mysqli_fetch_assoc() expects parameter 1 to be mysqli_result, boolean given in /www/htdocs/example/inc/functions.php on line 538

Which corresponds to this line of my php code:

while ($row = mysqli_fetch_assoc($result))

Maybe clone hash2 table from hash1 table

CREATE TEMPORARY TABLE hash2
        SELECT * FROM hash1;

sounds weird, but if I don't do this in that way, in my phpMyAdmin I get this error:

 #1137 - Can't reopen table: 'b'

I can't realize why my sql sentence works fine in my phpMyadmin but, when I construct it on my php file it doesn't works. Can anybody help me, please?

For further information, this is my PHP code:

    function getProductsFromFilteredQuery($connection, $filters, &$html)
{
    $sql = '';
    $m = count($filters); // $filters are an array of values like this: ['value1A, value2A', 'value1B, value2B', ...]

    $sql = 'CREATE TEMPORARY TABLE hash1
      SELECT * FROM
      (';

    for ($n = 0; $n < $m; $n++)
    {
        $string                 = explode(', ', $filters[$n]);
        $feature_id         = $string[0];
        $feature_value  = $string[1];

        $sql .= "
        (
            SELECT DISTINCT feature_id AS fl, feature_value AS fv FROM gf_product_features WHERE feature_id = '" . $feature_id . "' AND feature_value = '" . $feature_value . "'
        )";

        if ($n < ($m - 1))
        {
            $sql .= ' UNION ';
        }
    }


    $sql .=  ') AS q;


      CREATE TEMPORARY TABLE hash2 -- In this line I get an error
        SELECT * FROM hash1;

        SELECT 
          p.id AS id, 
          p.main_image AS main_image, 
          p.type AS taxonomy, 
          p.name AS model, 
          p.sku AS sku, 
          p.price AS price, 
          b.brand_name AS brand_name, 
          b.brand_image AS brand_logo,
          pf.feature_value AS feature_value, 
          f.feature AS feature_label,
          f.id AS feature_id
        FROM
        (
          SELECT  a.*
          FROM    gf_product AS a
          INNER JOIN
          (
            SELECT product_id
            FROM
            (
              SELECT a.product_id , count(*) AS commons
              FROM   gf_product_features AS a
              INNER JOIN hash1 AS b 
                ON    a.feature_id = b.fl 
                AND   a.feature_value = b.fv 
              GROUP BY a.product_id 
              ) AS features
              WHERE commons = (SELECT count(*) AS count FROM hash2)  
            ) b1 ON a.id = b1.product_id 
          ) AS p
        INNER JOIN  gf_brands AS b 
            ON p.brand_id = b.id
        INNER JOIN  gf_product_features AS pf 
            ON pf.product_id = p.id   
        INNER JOIN  gf_features AS f 
            ON pf.feature_id = f.id
        ORDER BY    price ASC, 
                    feature_id ASC';

    $result = mysqli_query($connection, $sql);

    while ($row = mysqli_fetch_assoc($result)) // In this line I get an error too
    {
        // Do some stuff... and at last, return the resulting $html
    }
};

I finally could find the error. In my phpMyAdmin it worked as well because someone can execute several queries in the SQL console. There is no problem with it.

However, when coding an mySQL query through PHP you only can run one mySQL sentence at once. Well, there is an exception: You can use mysqli_multi_query + mysqli_more_results, or something like these. But as I was coded it, you can't.

So there is two options: rewrite the PHP code like described in the pages of the two links above, or doing several mysqli_query within the PHP function.

I decided to do it through the second option, so the working code is the following (Notice the comments after each mysqli_query):

function getProductsFromFilteredQuery($mysqli, $filters, &$html) {
$sql = '';
$m = count($filters);

$sql        = 'DROP TEMPORARY TABLE IF EXISTS hash1;';
$result = mysqli_query($mysqli, $sql); // A single query

$sql        = 'DROP TEMPORARY TABLE IF EXISTS hash2;';
$result = mysqli_query($mysqli, $sql); // Another single query

$sql        = 'CREATE TEMPORARY TABLE hash1
  SELECT * FROM
  (';

for ($n = 0; $n < $m; $n++)
{
    $string                 = explode(', ', $filters[$n]);
    $feature_id         = $string[0];
    $feature_value  = $string[1];

    $sql .= "
    (SELECT DISTINCT feature_id AS fl, feature_value AS fv FROM gf_product_features WHERE feature_id = '" . $feature_id . "' AND feature_value = '" . $feature_value . "')";

    if ($n < ($m - 1))
    {
        $sql .= ' UNION ';
    }
}


$sql .=  ') AS q1';
$result = mysqli_query($mysqli, $sql); // Another single query

$sql =  'CREATE TEMPORARY TABLE hash2
    SELECT * FROM hash1;';
$result = mysqli_query($mysqli, $sql);  // Another single query

$sql = 'SELECT 
              p.id AS id, 
              p.main_image AS main_image, 
              p.type AS taxonomy, 
              p.name AS model, 
              p.sku AS sku, 
              p.price AS price, 
              b.brand_name AS brand_name, 
              b.brand_image AS brand_logo,
              pf.feature_value AS feature_value, 
              f.feature AS feature_label,
              f.id AS feature_id
            FROM
            (
              SELECT  a.*
              FROM    gf_product AS a
              INNER JOIN
              (
                SELECT product_id
                FROM
                (
                  SELECT a.product_id , count(*) AS commons
                  FROM   gf_product_features AS a
                  INNER JOIN hash1 AS b 
                    ON    a.feature_id = b.fl 
                    AND   a.feature_value = b.fv 
                  GROUP BY a.product_id 
                  ) AS features
                  WHERE commons = (SELECT count(*) AS count FROM hash2)  
                ) b1 ON a.id = b1.product_id 
              ) AS p
            INNER JOIN  gf_brands AS b 
                ON p.brand_id = b.id
            INNER JOIN  gf_product_features AS pf 
                ON pf.product_id = p.id   
            INNER JOIN  gf_features AS f 
                ON pf.feature_id = f.id
            ORDER BY    price ASC, 
                        feature_id ASC';

$result = mysqli_query($mysqli, $sql);  // Another single query. The last one.

while ($row = mysqli_fetch_assoc($result))
{
    // My stuff here...
}
}; // @END of function