This is my SQL query
select sum(stock.total_in_stock) as total_in_stock,stock.name,stock.inventory_id FROM ( SELECT i.store_id,i.model_id,i. total_in_stock,i.id as inventory_id, m.* from `inventory` as `i` left join `model_store` as `ms` on `ms`.`store_id` = `i`.`store_id` left join `model` as `m` on `m`.`id` = `ms`.`model_id` where `i`.`model_id` = m.id and `m`.`status` = 1 and `ms`.`status` = 1 and `i`.`created_at` = (select max(si.created_at) from `inventory` as `si` where si.model_id = i.model_id AND si.store_id = i.store_id AND si.status=1 ORDER BY si.created_at DESC LIMIT 1 )) as stock group by `stock`.`model_id`
Basically, I am trying to retrieve the stock of a particular store on the latest date.
I have written this query in laravel as follows:-
$results = DB::table('inventory as i')
->selectRaw( 'sum(stock.total_in_stock) as total_in_stock,stock.name,stock.inventory_id FROM ( SELECT i.store_id,i.model_id,i. total_in_stock,i.id as inventory_id, m.* ')
->leftJoin('model_store as ms','ms.store_id','=','i.store_id')
->leftJoin('model as m','m.id','=','ms.model_id')
->where('i.model_id','=', 'm.id')
->where('m.status','=', 1)
->where('ms.status','=', 1)
->where('i.created_at','=',function($query){
$query->from('inventory as si')
->selectRaw('max(si.created_at)')
->whereRaw('si.model_id = i.model_id AND si.store_id = i.store_id AND si.status=1 ORDER BY si.created_at DESC LIMIT 1 )) as stock ')
->groupBy('stock.model_id');
})->get();
This gives me the following error:-
SQLSTATE[42000]: Syntax error or access violation: 1064 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 ')' at line 1
(SQL: select sum(stock.total_in_stock) as total_in_stock,stock.name,stock.inventory_id FROM ( SELECT i.store_id,i.model_id,i. total_in_stock,i.id as inventory_id, m.* from `inventory` as `i` left join `model_store` as `ms` on `ms`.`store_id` = `i`.`store_id` left join `model` as `m` on `m`.`id` = `ms`.`model_id` where `i`.`model_id` = m.id and `m`.`status` = 1 and `ms`.`status` = 1 and `i`.`created_at` = (select max(si.created_at) from `inventory` as `si` where si.model_id = i.model_id AND si.store_id = i.store_id AND si.status=1 ORDER BY si.created_at DESC LIMIT 1 )) as stock group by `stock`.`model_id`))
I need to apply pagination. So i have to write this query as above.
I tried writing the query using DB::select(). It returns correct records but unfortunately, I cannot use pagination with that.
Please help me writing the correct query in laravel.
Try getting the PDO instance to execute your query directly, something like this:
$PDO=DB::connection('mysql')->getPdo();
$stmt=$PDO->prepare("
select
sum(stock.total_in_stock) as total_in_stock,
stock.name,
stock.inventory_id
FROM
(SELECT
i.store_id,
i.model_id,
i.total_in_stock,
i.id as inventory_id,
m . *
from
`inventory` as `i`
left join `model_store` as `ms` ON `ms`.`store_id` = `i`.`store_id`
left join `model` as `m` ON `m`.`id` = `ms`.`model_id`
where
`i`.`model_id` = m.id
and `m`.`status` = 1
and `ms`.`status` = 1
and `i`.`created_at` = (select
max(si.created_at)
from
`inventory` as `si`
where
si.model_id = i.model_id
AND si.store_id = i.store_id
AND si.status = 1
ORDER BY si.created_at DESC
LIMIT 1)) as stock
group by `stock`.`model_id`
");
// you can use prepared statments too,
// you will need to place :status
// accordingly in your query
//$stmt->bindParam(':status', 1);
$stmt->execute();
$result = $stmt->fetchAll();
Good Luck!
Related
I wrote a stored procedure for reports, it is working fine with the mysql but when I call it from PHP, I get an error:
SQLSTATE[42000]: Syntax error or access violation: 1064
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 'NULL' at line 1
PHP :
$crm_reports = "CALL CRM_Report_Total_Prize_Redemption('".$CrmreportsFromDate."','".$CrmreportsToDate."',$CampaignID);";
$total_prize = Yii::app()->db->createCommand($crm_reports)->queryAll();
Here is my stored procedure
CREATE DEFINER=`esp_reward`#`%` PROCEDURE `CRM_Report_Total_Prize_Redemption`(
IN v_StartDate DATETIME,
IN v_EndDate DATETIME,
IN v_CampaignID INT
)
BEGIN
DROP TEMPORARY TABLE IF EXISTS temp_prize_redemption;
CREATE TEMPORARY TABLE temp_prize_redemption (
ItemID INT(10)
,Qty INT(11)
,BenefitName VARCHAR(500)
);
/************************************* Item Data ****************************/
SET #v_SelectPhysicalItemForPickWin = CONCAT(" SELECT cpw.ItemID AS PrizeID,cpw.Benefit AS BenefitName
,COUNT(DISTINCT PickWinWinnerID) AS Qty
,cpw.VoucherID,cpw.VoucherAmount,cpc.CampaignName
FROM crm_promotion_campaign AS cpc
INNER JOIN crm_receipt AS cr ON cr.CampaignID = cpc.CampaignID
INNER JOIN crm_pickwin_winner AS cpw ON cpw.PickWinID = cr.PickWinID
WHERE 1 AND cpc.CampaignID = ",v_CampaignID," AND cpw.BenefitType = '1'
GROUP BY PrizeID ");
SET #v_SelectPhysicalItemForPromotion = CONCAT(" SELECT crb.ItemID AS PrizeID,crb.BenefitName
,COUNT(DISTINCT ID) AS Qty,crb.VoucherID,crb.VoucherAmount,cpc.CampaignName
FROM crm_promotion_campaign AS cpc
INNER JOIN crm_receipt AS cr ON cr.CampaignID = cpc.CampaignID AND cr.TypeID = '1'
INNER JOIN crm_receipt_benefit AS crb ON crb.PromotionID = cr.PromotionID
WHERE 1 AND cpc.CampaignID = ",v_CampaignID," AND crb.BenefitTypeID = '1'
GROUP BY PrizeID ");
SET #ItemData = CONCAT(" SELECT PrizeID,SUM(Qty) AS Total,BenefitName FROM ( ",#v_SelectPhysicalItemForPickWin," UNION ",#v_SelectPhysicalItem, " ) AS ItemData GROUP BY PrizeID ");
SET #v_data = CONCAT("INSERT INTO temp_prize_redemption", #ItemData);
PREPARE s1 FROM #v_data;
EXECUTE s1;
DEALLOCATE PREPARE s1;
/************************************* e-Voucher Data ****************************/
SET #v_SelecteVoucherForPickWin = CONCAT(" SELECT cpw.VoucherID AS PrizeID,cpw.Benefit AS BenefitName
,COUNT(DISTINCT VoucherID) AS Qty
,cpw.VoucherID,cpw.VoucherAmount,cpc.CampaignName
FROM crm_promotion_campaign AS cpc
INNER JOIN crm_receipt AS cr ON cr.CampaignID = cpc.CampaignID
INNER JOIN crm_pickwin_winner AS cpw ON cpw.PickWinID = cr.PickWinID
WHERE 1 AND cpc.CampaignID = ",v_CampaignID," AND cpw.BenefitType = '3'
GROUP BY PrizeID ");
SET #v_SelecteVoucherForPromotion = CONCAT(" SELECT crb.VoucherID AS PrizeID,crb.BenefitName
,COUNT(DISTINCT VoucherID) AS Qty,crb.VoucherID,crb.VoucherAmount,cpc.CampaignName
FROM crm_promotion_campaign AS cpc
INNER JOIN crm_receipt AS cr ON cr.CampaignID = cpc.CampaignID AND cr.TypeID = '1'
INNER JOIN crm_receipt_benefit AS crb ON crb.PromotionID = cr.PromotionID
WHERE 1 AND cpc.CampaignID = ",v_CampaignID," AND crb.BenefitTypeID = '3'
GROUP BY PrizeID ");
SET #eVoucherData = CONCAT(" SELECT PrizeID,SUM(Qty) AS Total,BenefitName FROM ( ",#v_SelecteVoucherForPickWin," UNION ",#v_SelecteVoucherForPromotion, " ) AS ItemData GROUP BY PrizeID ");
SET #v_data = CONCAT("INSERT INTO temp_prize_redemption", #eVoucherData);
PREPARE s2 FROM #v_data;
EXECUTE s2;
DEALLOCATE PREPARE s2;
/************************************* Physical Voucher Data ****************************/
SET #v_SelectPhysicalVoucherForPickWin = CONCAT(" SELECT cpw.VoucherAmount AS PrizeID,cpw.Benefit AS BenefitName
,COUNT(DISTINCT VoucherAmount) AS Qty
,cpw.VoucherID,cpw.VoucherAmount,cpc.CampaignName
FROM crm_promotion_campaign AS cpc
INNER JOIN crm_receipt AS cr ON cr.CampaignID = cpc.CampaignID
INNER JOIN crm_pickwin_winner AS cpw ON cpw.PickWinID = cr.PickWinID
WHERE 1 AND cpc.CampaignID = ",v_CampaignID," AND cpw.BenefitType = '2'
GROUP BY PrizeID ");
SET #v_SelectPhysicalVoucherForPromotion = CONCAT(" SELECT crb.VoucherAmount AS PrizeID,crb.BenefitName
,COUNT(DISTINCT VoucherAmount) AS Qty,crb.VoucherID,crb.VoucherAmount,cpc.CampaignName
FROM crm_promotion_campaign AS cpc
INNER JOIN crm_receipt AS cr ON cr.CampaignID = cpc.CampaignID AND cr.TypeID = '1'
INNER JOIN crm_receipt_benefit AS crb ON crb.PromotionID = cr.PromotionID
WHERE 1 AND cpc.CampaignID = ",v_CampaignID," AND crb.BenefitTypeID = '2'
GROUP BY PrizeID ");
SET #PhysicalVoucherVoucherData = CONCAT(" SELECT PrizeID,SUM(Qty) AS Total,BenefitName FROM ( ",#v_SelectPhysicalVoucherForPickWin," UNION ",#v_SelectPhysicalVoucherForPromotion, " ) AS ItemData GROUP BY PrizeID ");
SET #v_data = CONCAT("INSERT INTO temp_prize_redemption", #PhysicalVoucherVoucherData);
PREPARE s3 FROM #v_data;
EXECUTE s3;
DEALLOCATE PREPARE s3;
SELECT * FROM temp_prize_redemption;
END$$
Can anyone please look into this and can give my any hint so i can solve this issues
This should be a comment, but it's a bit long.
When I have a week or two to spare I'll start trying to make sense of your SQL - but there are a narrow set of use cases for PREPARE/EXECUTE and this does not appear to be one of them.
There are (still) critical parts of your PHP code missing.
Your insert statements do not explicitly state the columns the input should match too (not always fatal).
By random chance someone might post a solution which matches your problem, but in case that does not happen, you should reduce your SQL and PHP down to the minimum necessary to reproduce the fault.
I'm trying to run this query:
$products = $this->product_model->where(function($query) use ($key) {
$query->whereHas('categories', function ($category) use ($key) {
$category->where('key', $key);
});
$query->orWhereHas('parent.categories', function ($category) use ($key) {
return $category->where('key', $key);
});
});
The parent relation is another product, so it's from the same table. The problem I'm having is in the query that this produces:
SELECT *
FROM `products`
WHERE (
(SELECT count(*)
FROM `categories`
INNER JOIN `category_product` ON `categories`.`id` = `category_product`.`category_id`
WHERE `category_product`.`product_id` = `products`.`id`
AND `key` = 'mens'
) >= 1
OR
(SELECT count(*)
FROM `products` AS `self_30ec5d4782a83841add518f618b9f59e`
WHERE `self_30ec5d4782a83841add518f618b9f59e`.`id` = `products`.`parent_product_id`
AND
(SELECT count(*)
FROM `categories`
INNER JOIN `category_product` ON `categories`.`id` = `category_product`.`category_id`
WHERE `category_product`.`product_id` = `products`.`id`
AND `key` = 'mens'
) >= 1
) >= 1
)
In the sub-query after the OR I need this line:
WHERE `category_product`.`product_id` = `products`.`id`
To be this:
WHERE `category_product`.`product_id` = `self_30ec5d4782a83841add518f618b9f59e`.`id`
When I run this SQL on the database I get the correct result:
SELECT *
FROM `products`
WHERE (
(SELECT count(*)
FROM `categories`
INNER JOIN `category_product` ON `categories`.`id` = `category_product`.`category_id`
WHERE `category_product`.`product_id` = `products`.`id`
AND `key` = 'mens'
) >= 1
OR
(SELECT count(*)
FROM `products` AS `self_30ec5d4782a83841add518f618b9f59e`
WHERE `self_30ec5d4782a83841add518f618b9f59e`.`id` = `products`.`parent_product_id`
AND
(SELECT count(*)
FROM `categories`
INNER JOIN `category_product` ON `categories`.`id` = `category_product`.`category_id`
WHERE `category_product`.`product_id` = `self_30ec5d4782a83841add518f618b9f59e`.`id`
AND `key` = 'mens'
) >= 1
) >= 1
)
But I'm not sure how to make it do that in my PHP code. Also, is this the intended SQL output? Shouldn't it be doing what I want it to do? Since the sub-query is within the whereHas?
This is a bug in Laravel. has()/whereHas() does not handle conditions on self relationships or nested self relationships correctly.
I have submitted a pull request to correct this issue. You can view it here.
I don't know if it will be accepted, but you can take a look at it to see the code that was changed, and make the decision as to whether you want to manually update Laravel yourself or not. You can also follow it and wait to see the outcome.
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
i'm trying to convert this SQl query to QueryBuilder but i can't do it.
SELECT a.id, a.category_name, cat.Count
FROM `categories` a
LEFT OUTER JOIN (
SELECT `categories`.`category_parent` , COUNT(*) AS Count
FROM `categories`
GROUP BY category_parent
)
cat ON a.id = cat.category_parent
WHERE a.category_parent = 1
for example:
DB::table('users')
->join('contacts',DB::raw("a.id = cat.category_parent"),function($query){
$query->select(DB::raw("`categories`.`category_parent` , COUNT( * ) AS Count"))
->from('contacts')
->groupBy('category_parent')
->where(DB::raw("a.category_parent = 1"))
->get();
how to fix this method in laravel. thanks
Try getting the PDO instance to execute your query directly:
$PDO=DB::connection('mysql')->getPdo();
$stmt=$PDO->prepare("
SELECT a.id, a.category_name, cat.Count
FROM `categories` a
LEFT OUTER JOIN (
SELECT `categories`.`category_parent` , COUNT(*) AS Count
FROM `categories`
GROUP BY category_parent
)
cat ON a.id = cat.category_parent
WHERE a.category_parent = :category_parent
");
$stmt->bindParam(':category_parent', 1);
$stmt->execute();
$result = $stmt->fetchAll();
I have a query like that in one of my projects running on laravel 4.
Good Luck!
I'm new to mysql and I have a problem with selecting data from mysql database:
$post_id = 3;
$current_user_id = 1;
$query = "SELECT `comments`.*, `users`.`username`, `users`.`image` FROM (`comments`)
LEFT JOIN `users` ON `comments`.`user_id` = `users`.`id`
WHERE `comments`.`post_id` = '$post_id'
AND `comments`.`status` = 1
AND `users`.`status` = 1
ORDER BY `comments`.`date` desc";
This select, selects all approved comments from database, but also, in this select, I need all unapproved comments of $current_user_id,
Result must look like:
[all approved post comments] + [all unapproved post comments of $current_user_id]
not sure if this will really work, but just give a try and see. I can't test the query since we don't have the schema.
SELECT `comments`.*, `users`.`username`, `users`.`image` FROM (`comments`)
LEFT JOIN `users` ON `comments`.`user_id` = `users`.`id`
WHERE `comments`.`post_id` = '$post_id'
AND (
(`comments`.`status` = 1 AND `users`.`status` = 1)
OR
( `comments`.`status` = 0 AND `users`.`id`= '$current_user_id' )
)
ORDER BY `comments`.`date` desc
What I thought is select all the approved comments OR ( comments that are not approved, but from this user ). You might have to alter the query till you get what you really needed, I'm just giving you the idea, not the exact query. Hope this will help you.
SELECT `comments`.*, `users`.`username`, `users`.`image` FROM (`comments`)
LEFT JOIN `users` ON `comments`.`user_id` = `users`.`id`
WHERE `comments`.`post_id` = '$post_id'
AND `comments`.`status` = 1
AND `users`.`status` = 1
UNION ALL
SELECT `comments`.*, `users`.`username`, `users`.`image` FROM (`comments`)
LEFT JOIN `users` ON `comments`.`user_id` = `users`.`id`
WHERE `comments`.`post_id` = '$post_id'
AND `comments`.`status` = 0
AND `users`.`id` = '$current_user_id'
ORDER BY `comments`.`date` desc