use no join. cake php - cakephp

I have the following code.
var $uses = array('TABLE1','TABLE2','TABLE3');
function test() {
$this->Table1->updateAll(
array('Table1.field1' => 'some value'),
array('Table1.field1 ' => 'some condition')
);
......
.....
problem is that when I try to update only one table...Table1, it joins other tables with it.
UPDATE
`Table1`
LEFT JOIN
`Table2`
ON
(`Table1`.`id` = `Table2`.`uid`)
LEFT JOIN
`Table3`
ON
(`Table1`.`Table3_id` = `Table3`.`id`)
SET
`Table1`.`field1` = 1
WHERE
some condition.......
How can I not join the table and run update only on Table1?
Edit:
I used this but did not work :
$this->Table1->unBindModel(array(hasMany => array('Table2', 'Table3')));

firstly, stop using $uses. it will only cause you more pain than needed.
to avoid the joins use Model::unbindModel(array('relationType' => array('Relation')) http://book.cakephp.org/view/1045/Creating-and-Destroying-Associations-on-the-Fly

Try setting your recursive level to -1. I'm not sure whether this affects Update calls but it's worth a try.
$this->Table1->recursive = -1;
$this->Table1->updateAll(...);

Related

Why Manual prefetch (via select/columns) not supported with accessor 'multi'?

When I run code:
return $self->result_source->schema->resultset('Locality')->search(
{
'addresses_view.usage' => 0
,'me.id' => $self->id
}
,{
join => { servers => 'addresses_view' }
}
);
The next sql query generated:
SELECT
"me"."id", "me"."active", "me"."priority",
"me"."country_id", "me"."name"
FROM "localities" "me"
LEFT JOIN "servers" "servers" ON "servers"."locality_id" = "me"."id"
LEFT JOIN "pool_addresses_view" "addresses_view" ON "addresses_view"."server_id" = "servers"."id"
WHERE ( ( "addresses_view"."usage" = ? AND "me"."id" = ? ) )
And executed OK.
But when I want to add columns to 'SELECT'
,'+columns' => [ 'addresses_view.ip', 'addresses_view.id' ]
I get error: Manual prefetch (via select/columns) not supported with accessor 'multi'
I have found same qestion at www.mail-archive.com/dbix-class#, but I do not understand how pass the columns attribute to search_related as well to restrict the columns to select
Is there a way to add columns to 'SELECT' clause?
DBIx::Class::ResultSet#prefetch is just sugar which internally populates the join and columns attributes.
DBIx::Class::Manual::Joining contains lots of useful info about what's possible and how which should answer your question.

How do you apply multiple conditions to a leftjoin on a db_select?

I'm trying to join the Fivestar ratings for each node so I can sort them by rating. The problem is the Fivestar values I'm querying on are stored in votingapi_cache as multiple rows per node (vote count and the average rating), so I want to do the following:
...
LEFT JOIN votingapi_cache fivestar
ON fivestar.entity_id = node.nid
AND fivestar.function = 'average'
I've tried the following code, but the problem is the check on "fivestar.function = 'average'" is added to the where clause which eliminates all nodes that have no votes.
$query->leftjoin('votingapi_cache', 'fivestar', 'fivestar.entity_id = n.nid');
$query->condition('fivestar.function', 'average', '=');
$query->addField('fivestar', 'value', 'average_rating');
Ok, the first time I tried this I must have done something wrong, but here's the solution:
$query->leftjoin('votingapi_cache', 'fivestar', "fivestar.entity_id = n.nid AND fivestar.function = 'average'");
Ok, the first time I tried this I must have done something wrong, but here's the solution:
$query->leftjoin('votingapi_cache', 'fivestar', "fivestar.entity_id = n.nid AND fivestar.function = 'average'");
Here some multiple join conditions with an IN condition inside the join with implode PHP array to get correct results.
$query->leftJoin('element_item','ei','ei.id = ei.id2 AND (ei.param = '.$entity_param.' AND ei.id IN ('.implode(',',$records).'))');

Zend DB Select nested Joins

I'm trying to realize the following query with zend db select:
SELECT `uac`.`uid`, `u`.`uid`, `g`.`groupid`, `g`.`packageid`
FROM `user_has_data` AS `uac`
INNER JOIN `users` AS `u` ON u.uid = uac.uid
LEFT JOIN (`user_in_group` AS `uig`
INNER JOIN `groups` AS `ag` ON (ag.groupid = uig.groupid) AND (ag.packageid = 2)
) AS `g` ON uac.uid = g.uid
WHERE (uac.dataid = '3') AND (u.uname LIKE 'test%')
GROUP BY `u`.`uid`
I got the following, but got stuck when trying to convert the nested join to zend structure:
$select = $db->select()->from(array('uac' => 'user_has_data'), array('uac.uid'))
->join(array('u' => 'users'), 'u.uid = uac.uid', array('uid', 'uname'))
->joinLeft(array('uig' => 'user_in_groups'), 'uig.uid = uid', array('agid' => 'uig.groupid'))
->join(array('ag' => 'groups'), '(ag.agid = uig.groupid) AND ( ag.packageid = '.$packageid.')', array('packageid'))
->where('uac.dataid = ?', $dataid)
->where('(u.uname LIKE ?)', $value)
->group('u.uid');
Is it possible to get the given sql query into a suitable structure for zend db select? I need a select object for further handling in a paginator, so if this is not possible I have to make a straight forward sql query.
I don't believe you can do a nested join like that with Zend_Db_Select. Your best bet is to create your own paginator adapter (it's easier than you might think, look at the Select one) and manage the LIMIT part of the SQL yourself.
I know the question is old, but i think people might still benefit from the right answer for this question.
That nested join is the same as
SELECT * FROM `user_in_group` AS `uig`
INNER JOIN `groups` AS `ag` ON (ag.groupid = uig.groupid) AND (ag.packageid = 2)
So this should work just fine.
$subquery = $db->select()
->from(array('uig' => 'user_in_groups'),'*')
->joinInner(array('ag'=>'groups'),'(ag.groupid = uig.groupid) and (ag.packegeid = 2)',array('*'));
$select = $db->select()->from(array('uac' => 'user_has_data'), array('uac.uid'))
->join(array('u' => 'users'), 'u.uid = uac.uid', array('uid', 'uname'))
->joinLeft('g'=>$subquery), 'uac.uid = g.uid', array('g.groupid', 'g.packageid'))
->where('uac.dataid = ?', $dataid)
->where('(u.uname LIKE ?)', $value)
->group('u.uid');

What is the problem with the logic in my UPDATE statement?

I would appreciate some help with an UPDATE statement.
I want to update tblOrderHead with the content from tblCustomer where the intDocumentNo corresponds to the parameter #intDocumentNo. But when I run the my statement, the order table is only updated with the content from the first row of the customer table.
What is the problem with my logic?
I use Microsoft SQL Server.
Thanks,
Stefan
UPDATE dbo.tblOrderHead
SET dbo.tblOrderHead.intCustomerNo = #intCustomerNo ,
dbo.tblOrderHead.intPaymentCode = dbo.tblCustomer.intPaymentCode,
dbo.tblOrderHead.txtDeliveryCode = dbo.tblCustomer.txtDeliveryCode,
dbo.tblOrderHead.txtRegionCode = dbo.tblCustomer.txtRegionCode,
dbo.tblOrderHead.txtCurrencyCode = dbo.tblCustomer.txtCurrencyCode,
dbo.tblOrderHead.txtLanguageCode = dbo.tblCustomer.txtLanguageCode
FROM dbo.tblOrderHead
INNER JOIN dbo.tblCustomer ON dbo.tblOrderHead.intOrderNo = #intDocumentNo
Solution
If anyone as stupid as me out there thing the same thing, this is how you solve it:
UPDATE dbo.tblOrderHead
SET dbo.tblOrderHead.intCustomerNo = #intCustomerNo ,
dbo.tblOrderHead.intPaymentCode = dbo.tblCustomer.intPaymentCode,
dbo.tblOrderHead.txtDeliveryCode = dbo.tblCustomer.txtDeliveryCode,
dbo.tblOrderHead.txtRegionCode = dbo.tblCustomer.txtRegionCode,
dbo.tblOrderHead.txtCurrencyCode = dbo.tblCustomer.txtCurrencyCode,
dbo.tblOrderHead.txtLanguageCode = dbo.tblCustomer.txtLanguageCode
FROM dbo.tblOrderHead
INNER JOIN dbo.tblCustomer ON dbo.tblOrderHead.intCustomerNo = dbo.tblCustomer.intCustomerNo
AND dbo.tblOrderHead.intOrderNo = #intDocumentNo
Problem is that, you are not specifying the condition on which the 2 tables tblOrderHead, tblCustomer need to be joined!
you need something like
INNER JOIN dbo.tblCustomer
ON dbo.tblOrderHead.someColumn = dbo.tblCustomer.someColumn
and dbo.tblOrderHead.intOrderNo = #intDocumentNo

Update field from another table

Is there a better way to write the following simple SQL Server 2005 update statement? This just seems a bit messy inefficient.
UPDATE QuotationItem
SET Recurring_Cost =
(SELECT TOP (1) Recurring_Cost
FROM Products
WHERE (Remote_ID = QuotationItem.Product_ID))
WHERE (Quotation_ID = 115)
Thanks,
Nick
How About using a join
UPDATE QuotationItem
SET Recurring_Cost = p.recurring_cost
FROM QuotationItem q join Products p on q.Product_ID = p.Remote_ID
WHERE q.Quotation_ID = 115
Is your TOP 1 really needed? If it is, since you don't specify an ordering, you've got pretty random results from your query anyway! If it is not really necessary, this will do:
UPDATE q
SET Recurring_Cost = p.RecurringCost
FROM QuotationItem q
INNER JOIN
Products p
ON p.Remote_ID = q.Product_ID
WHERE q.Quotation_ID = 115

Resources