Issue with an mySQL sentence including two temporary table creation - php

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

Related

How to correct Conditional WHERE and JOIN sql table request?

I'm trying to select an specific information from a table that depends on the conditions of two other tables. When I try separate conditions work, but when I try to work with two conditions does not.
With this I get the correct data from table:
$sql = "SELECT * FROM commerce_order WHERE m_key = 'total'";
And with this I also get the result from table:
$sql = "SELECT *
FROM commerce_order M
JOIN commerce_order_items I
ON M.item_id = I.item_id
JOIN produtcs P
ON I.order_id = P.ID
WHERE status = 'complete'";
but when I try this I don't get any result:
$sql = "SELECT *
FROM commerce_order M
WHERE m_key = 'total'
JOIN commerce_order_items I
ON M.item_id = I.item_id
JOIN produtcs P
ON I.order_id = P.ID
WHERE status = 'complete'";`
I expected the first code result to be filtered by the second code condition. I know which are the values from the first table that should return, but I don't get any.
You can't put WHERE m_key = 'total' before JOIN all your WHERE clauses should go after all your JOINs:
$sql = "SELECT *
FROM commerce_order M
JOIN commerce_order_items I
ON M.item_id = I.item_id
JOIN produtcs P
ON I.order_id = P.ID
WHERE status = 'complete' AND m_key = 'total'";

How to fetch data from database in Magento with LIKE keyword?

I want a select query which fetch the data from database with "like" keyword
eg.
select product name, image , description
from table where product name LIKE "'.$name'";
I want it in Magento that how to fetch this fields from database in Magento. My existing query is:
$sql = "
SELECT value FROM catalog_product_entity_varchar
WHERE entity_type_id = (
SELECT entity_type_id FROM eav_entity_type WHERE entity_type_code = 'catalog_product') AND attribute_id = (SELECT attribute_id FROM eav_attribute WHERE attribute_code = 'name' AND entity_type_id = (SELECT entity_type_id FROM eav_entity_type WHERE entity_type_code = 'catalog_product')
)
";
Now the join query is :-
<?php
$sql = "
SELECT p.entity_id , pv.value as name , pt.value as description , GROUP_CONCAT (DISTINCT ( cp.category_id ) SEPARATOR ', ') as categories , GROUP_CONCAT (DISTINCT (pm.value) SEPARATOR ', ') as imagesPath
FROM catalog_product_entity as p
INNER JOIN catalog_product_entity_varchar as pv on pv.entity_id = p.entity_id and pv.attribute_id = 71
INNER JOIN catalog_product_entity_text as pt on pt.entity_id = p.entity_id and pt.attribute_id = 72
INNER JOIN catalog_category_product as cp on cp.product_id = p.entity_id
LEFT JOIN catalog_product_entity_media_gallery as pm on pm.entity_id = p.entity_id and pm.attribute_id = 88
GROUP BY cp.product_id , pm.entity_id " ;
foreach($readConnection->fetchAll($sql) as $orders)
{
?>
<?php echo $orders['name']; ?>
<?php echo $orders['description']; ?>
<?php
}
?>
This one is correct code to fetch the name and description of item in LIKE clause
Thank you so much #Halfer :)
$sql = SELECT p.`entity_id`, pv.`value` as name, pt.`value` as description
FROM `catalog_product_entity` as p
INNER JOIN `catalog_product_entity_varchar` as pv on pv.`entity_id` = p.`entity_id` and pv.`attribute_id` = 71
INNER JOIN `catalog_product_entity_text` as pt on pt.`entity_id` = p.`entity_id` and pt.`attribute_id` = 72
Where pv.value LIKE '%hp%';
$sql_jacket = "SELECT entity_id FROM customer_entity where email
like '".$_REQUEST['useremail']."'";
$result_jacket = $conn->query($sql_jacket);
if ($result_jacket->num_rows > 0)
{
while($row_jacket = $result_jacket->fetch_assoc())
{
$result1['user_status']=1;
}
}

How to join with unknown condition like pivot in mysql

I have the following code to
public function get_posted_questions($data) {
include dirname(__FILE__) . "/database.php";
$user_db_name = $dbconfig[$data['college_id']]['database'];
if (isset($data['start'])) {
$start = $data['start'];
} else {
$start = 0;
}
if (isset($data['end']) and ! empty($data['end'])) {
$end = $data['end'];
} else {
$end = 30;
}
/*
* multiple college database funda here goes
*/
$max_college_id = "
SELECT DISTINCT college_id
FROM just_ask_question
WHERE
status = '1'
AND isDeleted = '0'
AND college_id !='0'
ORDER BY id DESC
LIMIT $start, $end
";
$max_college_id_run = mysql_query($max_college_id);
$question_data = array();
$question_query = "
SELECT
Q.id,
Q.title,
Q.description,
Q.user_id,
Q.college_id,
Q.datetime,
IFNULL(GROUP_CONCAT(DISTINCT T.name),'') AS tags,
IFNULL(CONCAT_WS(' ',U.firstName,U.lastName),'') AS user_name
IFNULL(U.image,'') AS image,
IFNULL(V.id,'') AS no_of_view,
IFNULL(Vote.upvote,'') AS up_vote,
IFNULL(answer.id,0) AS no_of_answer,
IFNULL(is_upvote,0) AS upvote_status,
category_name
FROM just_ask_question AS Q
LEFT JOIN just_ask_question_tag Qt
ON Qt.question_id = Q.id
LEFT JOIN just_ask_tag T
ON T.id = Qt.tag_id
LEFT JOIN just_ask_category
ON just_ask_category.id = Q.category_id
LEFT JOIN
(
SELECT COUNT(id) as id, question_id FROM just_ask_answer
) AS answer ON answer.question_id = Q.id
";
while ( $row = mysql_fetch_assoc($max_college_id_run) ) {
$user_db_name = $dbconfig[$row['college_id']]['database'];
$question_query .= "
CASE WHEN Q.college_id = '".$row['college_id']."'
THEN LEFT JOIN $user_db_name.users U ON U.id = Q.user_id
";
}
$question_query .= "
LEFT JOIN
(
SELECT count(id) AS id, question_id FROM just_ask_view
) AS V ON V.question_id = Q.id
LEFT JOIN
(
SELECT
COUNT(upvote) as upvote,
question_id
FROM just_ask_upvote_downvote
WHERE upvote = '1' AND is_question = '1'
GROUP BY question_id
) AS Vote
ON Vote.question_id = Q.id
LEFT JOIN
(
SELECT
IF(COUNT(id) > 0,1,0) AS is_upvote,
question_id
FROM just_ask_upvote_downvote
WHERE
upvote = '1'
AND college_id = '" . $data['college_id'] . "'
AND user_id = '" . $data['user_id'] . "'
AND is_question = '1'
) AS Is_Vote
ON Is_Vote.question_id = Q.id
WHERE
Q.status = '1'
AND Q.isDeleted = '0'
AND CASE
WHEN Q.visibility = 0 AND Q.college_id != 0 THEN Q.college_id = '" . $data['college_id'] . "'
ELSE true
END
";
if (!empty($data['search_text'])) {
$search_text = $data['search_text'];
$question_query .= " and (Q.title like '%$search_text%' or Q.description like '%$search_text%' or T.name like '%$search_text%')";
}
$question_query .= " group by Q.id order by Q.id desc limit $start,$end";
$question_query_run = mysql_query($question_query);
/* get weather question exist */
$check_num_rows = mysql_num_rows($question_query_run);
if ($check_num_rows > 0) {
while ($row = mysql_fetch_assoc($question_query_run)) {
if ($row['image'] != '') {
$row['thumbnail'] = USER_THUMBNAIL_URL . $row['image'];
$row['image'] = IMAGE_URL . $row['image'];
} else
$row['thumbnail'] = '';
$question_data[] = $row;
}
$status['statuscode'] = "1";
$status['statusmessage'] = "ok";
$status['question_data'] = $question_data;
$response['response'] = $status;
echo json_encode($response);
die();
}else {
$status['statuscode'] = "2";
$status['statusmessage'] = "There is no record found";
$response['response'] = $status;
echo json_encode($response);
die();
}
}
AND the db config file like which contain the database name information
like
$dbconfig['1'] = array(
'host' => 'localhost',
'user_name' => 'root',
'password' => 'test123*',
'database' => 'staging_myuniversity'
);
$dbconfig['2'] = array(
'host' => 'localhost',
'user_name' => 'root',
'password' => 'test123*',
'database' => 'staging_myuniversity_dias'
);
the database are reside on same server and with full permission.
the query generate like this
select Q.id,Q.title,Q.description,Q.user_id,Q.college_id,
Q.datetime,
ifnull(group_concat(distinct T.name),'') as tags,
ifnull(CONCAT_WS(' ',
U.firstName,U.lastName),'') as user_name,
ifnull(U.image,
'') as image,ifnull(V.id,'') as no_of_view,
ifnull(Vote.upvote,
'') as up_vote,
ifnull(answer.id,0) as no_of_answer,
ifnull(is_upvote,
0
) as upvote_status,
category_name
from just_ask_question as Q
left join just_ask_question_tag Qt on Qt.question_id = Q.id
left join just_ask_tag T on T.id = Qt.tag_id
left join just_ask_category on just_ask_category.id = Q.category_id
left join
( SELECT count(id) as id,question_id
from just_ask_answer
) as answer on answer.question_id = Q.id case when Q.college_id = '1' then
left join staging_myuniversity.users U on U.id = Q.user_id case when Q.college_id = '12'then
left join campify_solutions_mathura.users U on U.id = Q.user_id case when Q.college_id = '4' then
left join staging_myuniversity_nit_kkr.users U on U.id = Q.user_id case when Q.college_id = '2' then
left join staging_myuniversity_dias.users U on U.id = Q.user_id
left join
( SELECT count(id) as id,question_id
from just_ask_view
) as V on V.question_id = Q.id
left join
( SELECT count(upvote) as upvote,question_id
from just_ask_upvote_downvote
where upvote = '1'
and is_question = '1'
group by question_id
) as Vote on Vote.question_id = Q.id
left join
( SELECT if(count(id) > 0,1,0) as is_upvote,question_id
from just_ask_upvote_downvote
where upvote = '1'
and college_id = '1'
and user_id = '1'
and is_question = '1'
) as Is_Vote on Is_Vote.question_id = Q.id
where Q.status = '1'
and Q.isDeleted = '0'
and case when Q.visibility = 0
and Q.college_id != 0 then Q.college_id = '1' else true end
group by Q.id
order by Q.id desc
limit 0,30
I need to make the join on different databases based on college id
first i fetch the distinct college id from the question then make a loop
for college id and try to make join condition but i am getting error there is any suggestion and help
I won't help you with entire query (I'll just list some concerns), but this "case-join" might be solved with UNION ALL subquery this way:
INNER JOIN (
SELECT 1 AS college_id, id, firstName, lastName, image
FROM staging_myuniversity.users
UNION ALL
SELECT 12 AS college_id, id, firstName, lastName, image
FROM campify_solutions_mathura.users
UNION ALL
...
) AS U ON U.college_id = Q.college_id AND U.id = Q.user_id
When you join counters with subqueries like SELECT count(), some_id use GROUP_BY some_id as well. Otherwise you'll count all rows in table and join this result for one (first/random) id only (if it passes without error).
It looks like You use LEFT JOIN too much. It means attach to the result on left regardless if any row on the right matches (joins null columns then). It's slow, gives large data sets and results with nulls for most of these columns seems useless.
Join subquery with GROUP BY clause to get concatenated tags
If large portion of this data will be repeated across the rows (see: N+1 problem) splitting queries (and merging subsets to common "header") might be a good idea.
Build your query one step at a time. Test subqueries if you're not sure of its results. Start with resource consuming parts - it might get slow at some point and you'll end up splitting it anyway.
... case when Q.college_id = '1' then left join ...
does not make sense. What are you trying to do?
Performance tip: Don't use LEFT JOIN ( SELECT ... ) Instead of that and IFNULL(...), simply do
SELECT ...,
IFNULL(( SELECT ... ), '') AS upvotes,
As for pivoting, I must say simply, and strongly, that some tasks are better left to your application code, not SQL.

Laravel / MySQL console different results

I am using laravel and I have this method inside one model.
When I run the query in PhpMyAdmin or in the MySQL console I get the expected result.
When running it in Laravel, I always get the same row which doesn't even fulfill the "where" statements in the query. Same luck when using ORDER BY RAND()
public static function getPotentialMatch($id, $genderId = NULL)
{
$query = "SELECT
student.id AS id,
(SELECT COUNT(*) FROM matches AS m WHERE m.local_student_id = student.id) AS matches
FROM
users AS user
JOIN students AS student
ON user.id = student.user_id
LEFT OUTER JOIN languages_student AS ls
ON student.id = ls.student_id
LEFT OUTER JOIN languages AS language
ON ls.language_id = language.id
LEFT OUTER JOIN courses AS course
ON student.course_id = course.id
WHERE ls.language_id IN
(
SELECT ls.language_id AS languageId
FROM languages_student AS ls
JOIN students AS student1
ON ls.student_id = student1.id
JOIN users AS user1
ON student1.user_id = user1.id
WHERE student1.id = " . $id . "
)
AND student.course_id IN
(
SELECT courseR.id AS affinityId
FROM courses AS course
JOIN course_affinities
ON course.id = course_affinities.course1_id
OR course.id = course_affinities.course2_id
JOIN courses AS courseR
ON (courseR.id = course_affinities.course1_id
AND courseR.id <> course.id)
OR (courseR.id = course_affinities.course2_id
AND courseR.id <> course.id)
WHERE course.id IN
(
SELECT student.course_id
FROM students AS student
WHERE student.id = " . $id . "
)
)
AND student.incoming = 0
AND student.active = 1
AND (
SELECT COUNT(*)
FROM matches AS m
WHERE m.local_student_id = student.id
) < 3
";
if ($genderId != NULL) {
$query .= " AND student.gender_id = " . $genderId;
}
$query .= " ORDER BY (SELECT COUNT(*) FROM matches AS m WHERE m.local_student_id = student.id)
LIMIT 1";
return DB::select(DB::raw($query));
}
Any ideas?

group subquery counts in mysql statement?

Wondering if this is possible or not. In the statement below I am getting counts from different tables. This prints our an array of totals for each user_id.
Is there any way to combine these totals so it returns a single array with the totals? I am using subqueries as joins were taking a hit performance-wise so joining is not an option.
$stmt = $db->prepare("
SELECT
(SELECT COUNT(*) FROM log1 WHERE log1.user_id = users.user_id AS l1,
(SELECT COUNT(*) FROM log2 WHERE log2.user_id = users.user_id AS l2,
(SELECT COUNT(*) FROM log3 WHERE log3.user_id = users.user_id AS l3,
(SELECT COUNT(*) FROM log4 WHERE log4.user_id = users.user_id AS l4
FROM computers
INNER JOIN users
ON users.computer_id = computers.computer_id
WHERE computers.account_id = :cw_account_id AND computers.status = :cw_status
");
$binding = array(
'cw_account_id' => $_SESSION['user']['account_id'],
'cw_status' => 1
);
$stmt->execute($binding);
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
At the moment I am doing something like this with the return to get the result I want:
foreach($result as $key)
{
$new['l1'] = $new['l1'] + $key['l1'];
$new['l2'] = $new['l2'] + $key['l2'];
$new['l3'] = $new['l3'] + $key['l3'];
$new['l4'] = $new['l4'] + $key['l4'];
}
return $new;
Use SUM aggregate function:
$stmt = $db->prepare("
SELECT
SUM((SELECT COUNT(*) FROM log1 WHERE log1.user_id = users.user_id)) AS l1,
SUM((SELECT COUNT(*) FROM log2 WHERE log2.user_id = users.user_id)) AS l2,
SUM((SELECT COUNT(*) FROM log3 WHERE log3.user_id = users.user_id)) AS l3,
SUM((SELECT COUNT(*) FROM log4 WHERE log4.user_id = users.user_id)) AS l4
FROM computers
INNER JOIN users
ON users.computer_id = computers.computer_id
WHERE computers.account_id = :cw_account_id AND computers.status = :cw_status
");
This query returns one row with total counts and your required result:
$new = $result[0];

Categories