optimise Yii2 MYSQL query - mysql

I need to optimise my code.it works but takes time and sometimes timeouts.
Objective selected columns from table 1 and table 2 must be combined in another table. duplicates are not allowed in the new table. TIA
$modelsc=Customers::find()->select('customer_id')->all();
$modelsp = Product::find()->select('product_no')->all();
foreach($modelsc as $modelc) {
$user = $connection->createCommand(
'SELECT product_no as product_no,:cust_no as fkcustomer_id
FROM product AS p
WHERE NOT EXISTS( SELECT pc.fkproduct_no
FROM
productcustomer AS pc
WHERE
pc.fkproduct_no = p.Product_no AND fkcustomer_id = :cust_no)');
$user->bindValue(':cust_no', $modelc->customer_id);
$modelsx = $user->queryAll();
Yii::$app->db->createCommand()->batchInsert('productcustomer', [ 'fkproduct_no', 'fkcustomer_id'], $modelsx)->execute(); }

looking to your code you could avoid the not exists clause an try using a left join checkn for null on pc.fkproduct_no
SELECT product_no as product_no,
:cust_no as fkcustomer_id
FROM product AS p
LEFT JOIN productcustomer AS pc ON pc.fkproduct_no = p.Product_no
AND fkcustomer_id = :cust_no
WHERE pc.fkproduct_no is null
Anyway be sure you have proper index on the column where of join condition
for table products an index on column Product_no
for table productcustomer a composite index on (fkcustomer_id, fkproduct_no)

Related

How to update quantity referencing another table php/mysql

I'm a bit of a noob and I'm sure this is fairly simple but I've tried different things and I can't get my head around it.
I have a product table that contains a category id and I want to set the quantity to 0 which is stored in another table.
This is the last thing I tried:
function wipeprod(){
UPDATE stock_available
INNER JOIN
product stock_available
ON
(
product.id_category_default != 3
OR
product.id_category_default != 10
OR
product.id_category_default != 943
)
SET
stock_available.quantity = 0;
}
Thanks in advance.
I suspect that you want to set column quantity in table stock_available to 0 for products that are not in categories 3, 10, and 943.
If so, you can use the update ... join syntax as follows:
update stock_available s
inner join product p on p.product_id = s.product_id
set s.quantity = 0
where p.id_category_default not in (3, 10, 943)
The main problems with your original query are:
the join is missing a predicate on product_id
you wanted AND condition rather than OR; NOT IN comes handy to shorten this.
You can use such an update statement by use of INNER JOIN :
UPDATE stock_available s
JOIN
(
SELECT id
FROM product
WHERE id_category_default NOT IN (3,10,943)
) AS p ON p.id = s.product_id
SET
s.quantity = 0;
where no need a proper query after the keyword JOIN

How to update/ make a view updatable in MYSQL

I have created a view via:
CREATE VIEW product_prices
AS SELECT Name, Price
FROM Products;
And I need to update it so prices under £10 are made 10% bigger apart from ones that are in category 3. These need to be looked up in a separate SELECT statement.
I have got this code so far but I'm getting the 1443 error that the definition of the view won't let me update it. How do I make it an updatable view?
UPDATE product_prices
SET Price = Price * 1.1
WHERE Name != (SELECT Name FROM Products WHERE Category_ID = 3)
AND Price < 10;
Use a join instead of <>:
UPDATE product_prices pp LEFT JOIN
Products p
ON p.name = pp.anme and p.Category_ID = 3
SET pp.Price = pp.Price * 1.1
WHERE p.Name IS NULL AND pp.Price < 10;
The issue is the operation on the table being updated, not the view definition.

Fetching MySQL data going through multiple tables

I'm wanting to do the following:
Select everything from product that matches the value of type_id from both tables product and system_type. Then with those matched results, match cat_id from both tables system_type and system_cat and then refine the final result where cat_type = 0 from the system_cat table.
Current SQL seems to have a syntax error:
SELECT * FROM product
JOIN system_type
USING (type_id)
JOIN system_cat
USING (cat_id)
WHERE cat_type = 0
What else I've tried:
SELECT * FROM product
JOIN system_type
USING system_type.type_id = product.type_id
JOIN system_cat
USING system_type.cat_id = system_cat.cat_id
WHERE system_cat.cat_type = 0
Try this. You may need to explicitely type out the columns you need
SELECT * FROM product as pr
INNER JOIN system_type as st
ON st.type_id = pr_id
INNER JOIN system_cat as sc
ONH st.cat_id = sc.cat_id
WHERE sc.cat_type = 0
Syntax changes when using table_name.column method. Use ON and not USING.
SELECT * FROM product
JOIN system_type
ON system_type.type_id = product.type_id
JOIN system_cat
ON system_type.cat_id = system_cat.cat_id
WHERE system_cat.cat_type = 0

Mysql query optimization issue

I am facing an query optimizing problem. Hope I will get some help.
The scenario is I have 4 tables.
Table 1 [asset_id, asset_name, User_id].
Table 2 [company_id, Company_name]
Table 3 [User_id, User_name]
Table 4 [Map_id, User_id, Company_id ]
My result will be to check Users from same company cannot able to upload same asset, checking of asset will be on COmpany level.
I have already written a query, that serves the purpose as well, but i need to eliminate the sub query for optimizing purpose.
The query I have written has a sub query.
My query is
SELECT COUNT(tg.asset_id)
FROM Table 1 tg
INNER JOIN Table 4 mcu
ON ((tg.User_id = mcu.User_id )
AND mcu.Company_id = (select Table 4.Company_id
from Table 4
where Table 4.User_id = 1))
WHERE tg.asset_name = 't1' ;
Hope this may be helpful::
SELECT
COUNT(tg.asset_id)
FROM Table 1 tg
INNER JOIN Table 4 mcu ON (tg.User_id = mcu.User_id and Company_id = ClientID )
WHERE tg.asset_name = 't1' and mcu.User_id = 1
The subquery seems unneeded for this query since it also uses Table 4.
SELECT COUNT(tg.asset_id) FROM Table 1 tg
INNER JOIN Table 4 mcu ON tg.User_id = mcu.User_id
WHERE tg.asset_name = 't1'
AND mcu.ClientID = mcu.Company_id
AND mcu.User_id = 1;

MySQL - Using column value for joining in the same query

I have three tables that looks something like this:
Table joins
|ID|JOIN_NAME|
1 persons
2 companies
Table information
|ID|JOIN_ID|
1 1
2 2
Table information_extra_persons
|ID|INFORMATION_ID|NAME|
1 1 John
Table information_extra_companies
|ID|INFORMATION_ID|NAME|
1 2 IBM
How can i join together these tables in one SQL? I've tried something like:
SELECT * FROM `information`
INNER JOIN `information_extra_(SELECT `name` FROM `joins` WHERE `id` = `join_id`)`
ON `information_extra_(SELECT `name` FROM `joins` WHERE `id` = `join_id`)`.`information_id` = `information`.`id`
but I can't get it to work. Of course this isn't my actual table setup, but it's the same principle. Does anyone know how to get all the info in just one SQL?
That's actually four tables, not three. This isn't just a nitpick - it looks as though the substance of your question is "how can I use the name of the table as part of the join criteria?" (ie. how can the information_extra_ tables be treated as a single table?)
To which the answer is: you can't. (Outside of dynamic SQL.)
In this specific case, the following should return what I think you are looking for:
select j.join_name joined_entity,
case when j.join_name = 'persons' then p.name
else c.name
end joined_entity_name
from information i
inner join joins j on i.join_id = j.id
left join information_extra_persons p on i.id = p.information_id
left join information_extra_companies c on i.id = c.information_id
Alternatively, a less efficient (but more general) approach might be:
select j.join_name joined_entity,
v.name joined_entity_name
from information i
inner join joins j on i.join_id = j.id
inner join (select 'persons' entity, information_id, name from information_extra_persons
union all
select 'companies' entity, information_id, name from information_extra_companies) v
on i.id = v.information_id and j.join_name = v.entity