WHERE in (subquery) clause yii - mysql

I have a mysql query like this
(SELECT
`notification`.`id`, `notification`.`user_id` AS `user_id`, `notification`.`activity_type`, `notification`.`source_id`, `event`.`title` as sourceName,concat_ws(" ",v.firstname,v.lastname) as ActorName
FROM
`notification`
INNER JOIN
`event`
ON
event.id = notification.source_id
INNER JOIN
`user` as v
ON
v.id = notification.user_id
AND
notification.activity_type = "checkin"
where
user_id in
(SELECT friend.friend_id from friend WHERE friend.user_id=1 AND friend.is_active=1))
UNION
(SELECT
`notification`.`id`, `notification`.`user_id` AS `user_id`, `notification`.`activity_type`, `notification`.`source_id`, concat_ws(" ",u.firstname,u.lastname) as sourceName,concat_ws(" ",v.firstname,v.lastname) as ActorName
FROM
`notification`
INNER JOIN
`user` as u
ON
u.id = notification.source_id
INNER JOIN
`user` as v ON v.id = notification.user_id
AND
notification.activity_type = "friend"
where user_id in
(SELECT friend.friend_id from friend WHERE friend.user_id=1 AND friend.is_active=1) )
And i want to write that query in yii2 and i dont know how to write subquery in where in clause.
So far i have done this
$query2 ->select(['notification.id', 'notification.user_id AS user_id', 'notification.activity_type', 'notification.source_id', 'concat_ws(" ",u.firstname,u.lastname) as sourceName','concat_ws(" ",v.firstname,v.lastname) as ActorName','user_image.imagepath as image'])
->from('notification' )
->innerJoin('user as u', 'u.id = notification.source_id')
->innerJoin('user_image','user_image.user_id = notification.user_id')
->innerJoin('user as v', 'v.id = notification.user_id AND notification.activity_type = "friend"')
->where('user_image.imagetype="profile"')
->andWhere(['user_id'=>('SELECT friend.friend_id from friend WHERE friend.user_id='.$id.' AND friend.is_active=1')]);
$query ->select(['notification.id','notification.user_id AS user_id','notification.activity_type', 'notification.source_id', 'event.title as sourceName','concat_ws(" ",v.firstname,v.lastname) as ActorName','organiser.image as image'])
->from('notification')
->innerJoin('event', 'event.id = notification.source_id')
->innerJoin('organiser','organiser.organiser_id = event.organiser_id')
->innerJoin('user as v', 'v.id = notification.user_id AND notification.activity_type = "checkin"')
->Where(['in', 'user_id', [488,489]])
->union($query2);
Which generates the command query like this
(SELECT
`notification`.`id`, `notification`.`user_id` AS `user_id`, `notification`.`activity_type`, `notification`.`source_id`, `event`.`title` AS `sourceName`, concat_ws(" ",v.firstname,v.lastname) as ActorName, `organiser`.`image` AS `image`
FROM
`notification`
INNER JOIN
`event`
ON
event.id = notification.source_id
INNER JOIN
`organiser`
ON
organiser.organiser_id = event.organiser_id
INNER JOIN
`user` `v`
ON
v.id = notification.user_id
AND
notification.activity_type = "checkin"
WHERE
`user_id` IN (:qp0, :qp1))
UNION
( SELECT
`notification`.`id`, `notification`.`user_id` AS `user_id`, `notification`.`activity_type`, `notification`.`source_id`, concat_ws(" ",u.firstname,u.lastname) as sourceName, concat_ws(" ",v.firstname,v.lastname) as ActorName, `user_image`.`imagepath` AS `image`
FROM
`notification`
INNER JOIN
`user` `u`
ON
u.id = notification.source_id
INNER JOIN
`user_image`
ON
user_image.user_id = notification.user_id
INNER JOIN
`user` `v`
ON
v.id = notification.user_id
AND
notification.activity_type = "friend"
WHERE
(user_image.imagetype="profile") AND (`user_id`=:qp2) )
But its not working,so what is the right syntax
and also feel free to give suggestion if where in could be write with inner join
that would make it very easy to write query
thank you

Try This
$query = (new Query())
->select('notification`.`id`, `notification`.`user_id` AS `user_id`, `notification`.`activity_type`, `notification`.`source_id`, `event`.`title` as sourceName,concat_ws(" ",v.firstname,v.lastname) as ActorName')
->from('notification')
->innerJoin('event' ,'event.id = notification.source_id')
->innerJoin('user v' ,'v.id = notification.user_id')
->where([
'user_id' => (new Query())
->select('friend.friend_id')
->from('friend')
->where([
'friend.user_id' => 1,
'friend.is_active' => 1
])
])->andWhere([
'notification.activity_type' => "checkin"
]);
$query2 = (new Query())
->select('`notification`.`id`, `notification`.`user_id` AS `user_id`, `notification`.`activity_type`, `notification`.`source_id`, concat_ws(" ",u.firstname,u.lastname) as sourceName,concat_ws(" ",v.firstname,v.lastname) as ActorName')
->from('notification')
->innerJoin('user v' ,'v.id = notification.user_id')
->where([
'user_id' => (new Query())
->select('friend.friend_id')
->from('friend')
->where([
'friend.user_id' => 1,
'friend.is_active' => 1
])
])->andWhere([
'notification.activity_type' => "checkin"
])->union($query)->all();

You can use Yii2 Query Builder, here is an example.
$subQuery = (new \yii\db\Query())->select([
'users.id as userId',
'users.first_name',
'users.username',
'users.last_name',
'users.sector_id',
])
->from(['users'])
->where(['=', 'role_id', 3])
->orWhere(['=', 'role_id', 2])
->groupBy('users.id');
$query = (new \yii\db\Query())->select(['user.*', 'user_address.*'])
->from(['user'=>$subQuery])
->leftJoin('user_address', 'user.userId = user_address.user_id')
->where(['between', 'latitude', $min_lat, $max_lat])
->andWhere(['between', 'longitude', $min_lon, $max_lon])
->groupBy('user.userId');

Related

Convert SQL Select Query to Magento Collection

I have a complex sql select query which actually returns sales report against specified categories. I want to load data as a collection to display but I'm not able to convert the query into Magento's equivalent getCollection statement. my query is below. thanks in advance
select
sfo.increment_id as 'orderid',
sfoi.sku,
sfoi.qty_ordered as 'qty',
IFNULL(sfoi.price_incl_tax-sfoi.discount_amount, 0) as 'productprice',
sfo.shipping_amount,
cost.value as 'price',
sfo.status,
sfo.created_at,
IF(ccp1.product_id IS NULL, 'no', 'yes') as sale,
IF(ccp2.product_id IS NULL, 'no', 'yes') as home
from sales_flat_order as sfo
join sales_flat_order_item as sfoi on sfo.entity_id = sfoi.order_id
join catalog_product_entity_decimal as cost on cost.entity_id = sfoi.product_id and cost.attribute_id = 79
left join catalog_category_product as ccp1 on sfoi.product_id = ccp1.product_id and ccp1.category_id = 8
left join catalog_category_product as ccp2 on sfoi.product_id = ccp2.product_id and ccp2.category_id = 7
where sfo.created_at between '2017-01-01' and '2017-01-02'
and sfo.status in ('processing','complete')
Magento collection statement
$collection = Mage::getModel('sales/order')->getCollection();
$collection->getSelect()->join(
array('sfoi' => $collection->getTable('sales/order_item')), 'main_table.entity_id=sfoi.order_id',
array('qty' => 'sfoi.qty_ordered', 'sku')
)->join(
array('cost' => 'catalog_product_entity_decimal'), 'cost.entity_id=sfoi.product_id and cost.attribute_id=79',
array('price' => 'cost.value')
)->joinLeft(
array('ccp1' => 'catalog_category_product'),
'sfoi.product_id = ccp1.product_id and ccp1.category_id = 8', null
)->joinLeft(
array('ccp2' => 'catalog_category_product'),
'sfoi.product_id = ccp2.product_id and ccp2.category_id = 7', null
);
$collection->addFieldToSelect('increment_id', 'orderid')
->addFieldToSelect('shipping_amount')
->addFieldToSelect('status')
->addFieldToSelect('created_at')
->addExpressionFieldToSelect(
'productprice',
'IFNULL((sfoi.price_incl_tax - {{discount_amount}}), "0")',
array(
'discount_amount' => 'sfoi.discount_amount'))
->addExpressionFieldToSelect(
'sale',
'IF({{product_id}} IS NULL, "no", "yes")',
array(
'product_id' => 'cpp1.product_id'))
->addExpressionFieldToSelect(
'home',
'IF({{product_id}} IS NULL, "no", "yes")',
array(
'product_id' => 'ccp2.product_id'))
->addAttributeToFilter('sfo.created_at', array(
'from' => '2017-01-01',
'to' => '2017-01-02',
'date' => true,
))
->addFieldToFilter('status', array('in' => array('processing','complete')));
...generated sql query
SELECT `main_table`.`increment_id` AS `orderid`,
`main_table`.`shipping_amount`,
`main_table`.`status`,
`main_table`.`created_at`,
`sfoi`.`qty_ordered` AS `qty`,
`sfoi`.`sku`,
`cost`.`value` AS `price`,
Ifnull(( sfoi.price_incl_tax - sfoi.discount_amount ), "0") AS
`productprice`,
IF(cpp1.product_id IS NULL, "no", "yes") AS `sale`,
IF(ccp2.product_id IS NULL, "no", "yes") AS `home`
FROM `sales_flat_order` AS `main_table`
INNER JOIN `sales_flat_order_item` AS `sfoi`
ON main_table.entity_id = sfoi.order_id
INNER JOIN `catalog_product_entity_decimal` AS `cost`
ON cost.entity_id = sfoi.product_id
AND cost.attribute_id = 79
LEFT JOIN `catalog_category_product` AS `ccp1`
ON sfoi.product_id = ccp1.product_id
AND ccp1.category_id = 8
LEFT JOIN `catalog_category_product` AS `ccp2`
ON sfoi.product_id = ccp2.product_id
AND ccp2.category_id = 7
WHERE ( `sfo`.`created_at` >= '2017-01-01 00:00:00'
AND `sfo`.`created_at` <= '2017-01-02 00:00:00' )
AND ( `status` IN( 'processing', 'complete' ) )

Multiple rows in a select with OR

I have this query and when I add a OR, return multiples rows, how I can fix this? I need another left join or Right join?
SELECT `images`.`id` as `id_image`, `images_lang`.`title` as `title`, `images_lang`.`autor` as `author`, `media_lang`.`file`, `category_lang`.`title` as `category`
FROM `images`
JOIN `images_lang` ON `images_lang`.`id_images` = `images`.`id`
JOIN `category_lang` ON `images`.`id_category` = `category_lang`.`id_category`
JOIN `media` ON `images`.`id` = `media`.`id_item`
JOIN `media_lang` ON `media`.`id` = `media_lang`.`id_media`
JOIN `relation` ON `relation`.`from_id` = `images`.`id`
JOIN `tag` ON `tag`.`id` = `relation`.`to_id`
JOIN `tag_lang` ON `tag`.`id` = `tag_lang`.`id_lang`
WHERE `media`.`table` = 'images'
AND `media_lang`.`id_lang` = '1'
AND `images_lang`.`id_lang` = '1'
AND `category_lang`.`id_lang` = '1'
AND `images`.`active` = 1
AND `relation`.`type` = 2
AND `tag_lang`.`id_lang` = '1'
AND `tag_lang`.`slug` = 'pa-am-oli'
OR `tag_lang`.`slug` = 'playa'
LIMIT 9
and the code in codeigniter, but I donĀ“t how add the or after the and ($keywords is an array for filter the elements)
$this->db->select('images.id as id_image, images_lang.title as title, images_lang.autor as author, media_lang.file, category_lang.title as category');
$this->db->from($this->table);
$this->db->join($this->table.'_lang',$this->table.'_lang.id_images = '.$this->table.'.id');
$this->db->join('category_lang',$this->table.'.id_category = category_lang.id_category');
$this->db->join('media',$this->table.'.id = media.id_item');
$this->db->join('media_lang','media.id = media_lang.id_media');
$this->db->where('media.table',$this->table);
$this->db->where('media_lang.id_lang',$id_lang);
$this->db->where($this->table.'_lang.id_lang', $id_lang);
$this->db->where('category_lang.id_lang', $id_lang);
$this->db->where('images.active', 1);
if($category){
$this->db->where('category_lang.title', $category);
}
if($keywords){
$this->db->join('relation', 'relation.from_id = '.$this->table.'.id');
$this->db->join('tag', 'tag.id = relation.to_id');
$this->db->join('tag_lang', 'tag.id = tag_lang.id_lang');
$this->db->where('relation.type', _IMAGES_2_TAGS_);
$this->db->where('tag_lang.id_lang', $id_lang);
foreach($keywords as $tag){
$this->db->or_where('tag_lang.slug', $tag);
}
}
if($from || $limit)
{
$this->db->limit((int)$limit, (int)$from);
}
$query = $this->db->get();
return $query->result_array();
I solved the query adding this (and a Select Distinct)
AND (`tag_lang`.`slug` = 'playa'
OR `tag_lang`.`slug` = 'pa-am-oli')
How I can add this in codeigniter?
I don't get what you need exactly, but if you want have just one line as a return by filtering using OR
In your case you should do the following:
WHERE (`media`.`table` = 'images' OR `tag_lang`.`slug` = 'playa')
AND (`media_lang`.`id_lang` = '1' OR `tag_lang`.`slug` = 'playa')
and so on, I hope that helps you and good luck!
Astute use of parentheses would solve your problem, but this is easier to read...
SELECT i.id id_image
, il.title
, il.autor author
, ml.file
, cl.title category
FROM images i
JOIN images_lang il
ON il.id_images = i.id
JOIN category_lang cl
ON cl.id_category = i.id_category
JOIN media m
ON m.id_item = i.id
JOIN media_lang ml
ON ml.id_media = m.id
JOIN relation r
ON r.from_id = i.id
JOIN tag t
ON t.id = r.to_id
JOIN tag_lang tl
ON tl.id_lang = t.id
WHERE m.table = 'images'
AND ml.id_lang = 1
AND il.id_lang = 1
AND cl.id_lang = 1
AND i.active = 1
AND r.type = 2
AND tl.id_lang = 1
AND tl.slug IN('pa-am-oli','playa')
LIMIT 9
... however, note that LIMIT without ORDER BY is fairly meaningless.

How to optimize subquery in select clause in mysql?

I have a subquery in select clause, like this
SELECT
`s`.`id` AS `id`,
`s`.`unit_id` AS `unit_id`,
`m`.`description` AS `description`,
`s`.`lot_no` AS `lot_no`,
(
(
(
SELECT COALESCE(SUM(`payment_amt`),0) AS `jmlh`
FROM `sb_ar_bill_sch`
WHERE `unit_id` = `s`.`unit_id` AND `lot_no` = `s`.`lot_no` AND `project_no` = `s`.`project_no` AND `debtor_acct` = `s`.`debtor_acct`
AND `bill_type` = 'S'
)
/
`s`.`sell_price`
)
*
100
) AS `persen_paid`
FROM `p_sis_rl_sales` `s`
JOIN `p_sis_pl_project` `p` ON `s`.`unit_id` = `p`.`unit_id` AND `s`.`project_no` = `p`.`project_no`
JOIN `p_sis_pm_lot` `l` ON `s`.`unit_id` = `l`.`unit_id` AND `s`.`project_no` = `l`.`project_no` AND `s`.`lot_no` = `l`.`lot_no`
JOIN `p_common_businessunit` `m` ON `s`.`unit_id` = `m`.`unit_id`
JOIN `v_la_lastowner` `o` ON `s`.`unit_id` = `o`.`unit_id` AND `s`.`project_no` = `o`.`project_no` AND `s`.`lot_no` = `o`.`lot_no`
WHERE
(
`s`.`contract_no` IS NOT NULL
AND
(
(
(
SELECT COALESCE(SUM(`payment_amt`),0) AS `jmlh`
FROM `sb_ar_bill_sch`
WHERE `unit_id` = `s`.`unit_id` AND `lot_no` = `s`.`lot_no` AND `project_no` = `s`.`project_no` AND `debtor_acct` = `s`.`debtor_acct`
AND `bill_type` = 'S'
)
/ `s`.`sell_price`
)
*
100
)
>=
100
)
ORDER BY `s`.`sales_date` DESC
I already indexed the table that I used.
Do I need to process hundreds of thousands of rows in one table?
The Query above takes a long time. How can the query above be optimized?

Magento collection join add alias

I want Mage_Adminhtml_Block_Dashboard_Orders_Grid setCollection rewrite.
I done :
public function setCollection($collection)
{
$connection = $collection->getConnection();
if(!Mage::helper("accountmanager")->isAdmin()){
$userId = Mage::helper("accountmanager")->getUserId();
$collection->getSelect()->joinInner(array('items_table'=>'sales_flat_order_item'),
'main_table.entity_id = items_table.order_id ',
null);
$collection->getSelect()->joinInner(array('e'=>'catalog_product_entity'),
'items_table.product_id = e.entity_id ',
null);
$collection->getSelect()->joinLeft(array('at_created_by'=>'catalog_product_entity_int'),
'(`at_created_by`.`entity_id` = `e`.`entity_id`) AND (`at_created_by`.`attribute_id` = 141) AND (`at_created_by`.`store_id` = 0) ',
null);
$collection->getSelect()->where("at_created_by.value = '".$userId."'");
}
exit($collection->getSelect());
parent::setCollection($collection);
}
result this:
SELECT `main_table`.*, `main_table`.`total_item_count` AS `items_count`, CONCAT_WS(' ', main_table.customer_firstname, main_table.customer_lastname) AS `customer`, `main_table`.`base_grand_total` AS `revenue` FROM `sales_flat_order` AS `main_table` INNER JOIN `sales_flat_order_item` AS `items_table` ON main_table.entity_id = items_table.order_id INNER JOIN `catalog_product_entity` AS `e` ON items_table.product_id = e.entity_id LEFT JOIN `catalog_product_entity_int` AS `at_created_by` ON (`at_created_by`.`entity_id` = `e`.`entity_id`) AND (`at_created_by`.`attribute_id` = 141) AND (`at_created_by`.`store_id` = 0) WHERE (store_id = '1') AND (at_created_by.value = '3')
this sql error : Error Code: 1052. Champ: 'store_id' dans where clause est ambigu
i think store_id no have alias 'main_table'.
How my query add alias??
please help me.
think you .

how to build nested select on zend db

Hi i have trouble with this query
SELECT * FROM(
SELECT `b`.*,`owner`.firstname,`owner`.lastname,`owner`.email,
(
SELECT COUNT(`ps`.profile_id) FROM `profile` AS `ps`
LEFT JOIN `xref_store_profile_brand` AS `xbp` ON `xbp`.profile_id = `ps`.profile_id
WHERE `xbp`.brand_id = b.brand_id AND ps.role = 'salesrep' AND `xbp`.store_id IS NULL
) AS `salesrepTotal`,
(
SELECT GROUP_CONCAT(`ms`.firstname) FROM `profile` AS `ps`
LEFT JOIN `xref_store_profile_brand` AS `xbp` ON `xbp`.profile_id = `ps`.profile_id
LEFT JOIN `member` AS `ms`ON `ms`.member_id = `ps`.member_id
WHERE `xbp`.brand_id = `b`.brand_id AND ps.role = 'salesrep' AND `xbp`.store_id IS NULL
) AS `salesrep`,
(
SELECT COUNT(`s`.store_id) FROM `store` AS `s`
LEFT JOIN `xref_store_profile_brand` AS `xbs` ON `xbs`.store_id = `s`.store_id
WHERE `xbs`.brand_id = `b`.brand_id AND `xbs`.brand_id IS NOT NULL
) AS `storeTotal`,
(
SELECT GROUP_CONCAT(`s`.name) FROM `store` AS `s`
LEFT JOIN `xref_store_profile_brand` AS `xbs` ON `xbs`.store_id = `s`.store_id
WHERE `xbs`.brand_id = `b`.brand_id AND `xbs`.brand_id IS NOT NULL
) AS `store`
FROM `brand` AS `b`
LEFT JOIN
(
SELECT `m`.firstname,`m`.lastname,`m`.email,`xspb`.brand_id FROM `member` AS `m`
LEFT JOIN `profile` as `p` ON `p`.member_id = `m`.member_id AND `p`.role = 'designer' AND `p`.isPrimary = 1
LEFT JOIN `xref_store_profile_brand` AS `xspb` ON `xspb`.profile_id = `p`.profile_id AND `xspb`.store_id IS NULL
) AS `owner` ON `owner`.brand_id =`b`.brand_id
GROUP BY `b`.brand_id
) AS `final`
how can i convert this in to Zend_Db_Select object?
Th main problem is
this part
SELECT `b`.*,`owner`.firstname,`owner`.lastname,`owner`.email,
(
SELECT COUNT(`ps`.profile_id) FROM `profile` AS `ps`
LEFT JOIN `xref_store_profile_brand` AS `xbp` ON `xbp`.profile_id = `ps`.profile_id
WHERE `xbp`.brand_id = b.brand_id AND ps.role = 'salesrep' AND `xbp`.store_id IS NULL
) AS `salesrepTotal`,
You need to use Zend_Db_Expr objects in your query and array structures for select AS.
below is the solution you are looking for:
<?php
$db = Zend_Db_Table::getDefaultAdapter();
// inner query
$sqlSalesRepTotal = $db->select()
->from(array('ps' => 'profile'))
->joinLeft(array('xbp' => 'xref_store_profile_brand'), 'xbp.profile_id = ps.profile_id')
->where('xbp.brand_id = b.brand_id')
->where('ps.role = ?', 'salesrep')
->where('xbp.store_id IS NULL');
// main query
$sql = $db->select()
->from(array('b' => 'brand'), array(
// NOTE: have to add parentesis around the expression
'salesrepTotal' => new Zend_Db_Expr("($sqlSalesRepTotal)")
))
->where('....')
->group('brand_id');
// debug
var_dump($db->fetchAll($sql));