Select only calculated columns in Propel - php

I'm trying to perform a selection with Propel which returns only calculated columns, but I allways have other columns selected.
For example:
$criteria = new MuestraQuery();
$criteria->clearSelectColumns()
->addAsColumn('numEspesores', 'count(distinct muestra.sal_espesor)')
Resulting query:
SELECT muestra.sal_id, muestra.sal_regimen,
-- ...
-- (ALL FIELDS OF THE TABLE HERE...)
-- ...
count(distinct muestra.sal_espesor) AS numEspesores
FROM muestra
I've been able to reduce the number of fields selected including only a field. For example, this query returns only two fields:
$criteria = new MuestraQuery();
$criteria->clearSelectColumns()
->select(MuestraTableMap::COL_SAL_ID)
->addAsColumn('numEspesores', 'count(distinct muestra.sal_espesor)')
Resulting query:
SELECT count(distinct muestra.sal_espesor) AS numEspesores,
muestra.sal_id AS "muestra.sal_id"
FROM muestra
¿Is there a way in Propel to select only computed columns?
I've seen columns are added in ModelCriteria->doSelect() based on protected ModelCriteria->isSelfSelected property, which is set in ModelCriteria->select() but not in addAsColumn() because it's from Criteria and it's not overriden in ModelCriteria.
Don't know if this is a bug or I'm doing something badly.

Just select the computed column that you added.
MuestraQuery::create()
->select(['numEspesores'])
->addAsColumn('numEspesores', 'count(distinct muestra.sal_espesor)')
->find();
Due to Propel's fluent api, you do not have to call the select method prior to the addAsColumn method, so you could even do the following:
MuestraQuery::create()
->addAsColumn('numEspesores', 'count(distinct muestra.sal_espesor)')
->select(['numEsesores'])
->find();

Related

Laravel: How to subselect two columns from another table in a query

Say I have the following tables:
event_relationships
id
user_id
relationship
primary_event_id
secondary_event_id
events
id
user_id
name
color
In my user model, I have my relationship setup like:
$this->hasMany(EventRelationships::class, 'user_id');
And each event relationship belongs to one user.
How can I use Laravel Eloquent to get a list of all the event relationships, but also get each event's name and color? Matching on the primary_event_id and secondary_event_id.
Is this possible with one query?
In pure eloquent, in the laravel way, that would be :
$eventRelationships = EventRelationships::with('primaryEvent', 'secondaryEvent')->get();
foreach($eventRelationships as $eventRelationship){
$primary_event_name = $eventRelationship->primaryEvent->name;
$secondary_event_name = $eventRelationship->secondaryEvent->name;
}
but it's in 2 queries. If you want only one query, you have to use a join :
$eventRelationships = EventRelationships::query()
->join('events as primary_events', 'events.id', 'event_relationships.primary_event_id')
->join('events as secondary_events', 'events.id', 'event_relationships.secondary_event_id')
->select('event_relationships.*', 'primary_events.name as primary_event_name', 'secondary_events.name as secondary_event_name')
->get();
foreach($eventRelationships as $eventRelationship){
$primary_event_name = $eventRelationship->primary_event_name;
$secondary_event_name = $eventRelationship->secondary_event_name;
}
It might be easier to use the first one as you manipulate eloquent object

Duplicated records in Yii2 GridView

It was working just fine, but I had to import data afresh in the existing order1 table which is related to order_item table on order.id = order_item.order_id and order_item.location_id = location.id
So to get the location in GridView of order1 table I had relation defined like so:
public function getLocation() {
return $this->hasOne(Location::className(), ['id' => 'location_id'])->viaTable('{{%order_item}}', ['order_id' => 'id']);
}
Now I have multiple records in the GridView. The query formed for the GridView is like:
SELECT `order1`.*
FROM `order1`
LEFT JOIN `order_item` ON `order1`.`id` = `order_item`.`order_id`
LEFT JOIN `location` ON `order_item`.`location_id` = `location`.`id`
where 1 ORDER BY `id` DESC
LIMIT 20;
How I can fix this as inner join or otherwise, so that it returns records only once from order1 table?
In GridView I am using location.location_title.
Note: there are multiple order items per order.
also Tried:
public function getOrderItem()
{
return $this->hasMany(OrderItem::className(), ['order_id' => 'id']);
}
public function getLocation()
{
return $this->hasOne(Location::className(), ['id' => 'location_id'])
->via('orderItem');
}
You need to add GROUP BY in your search model to ensure that orders will not be duplicated in query results:
$query->groupBy('order1.id');
Although hasOne() seems to be incorrect (if one order can have multiple items, then it could also have multiple locations), changing this to hasMany() will not fix GridView results. You need to be careful with one-to-many or many-to-many relations, usually you need to use GROUP BY to remove duplicates or adjust your DB structure or joins in search model, to avoid such situation.
BTW: Adding groupBy() in relation definition (getLocation()) is almost always incorrect. This is not a job of relation definition to handle grouping of main model results (you can be almost sure it will create issues with lazy loading).

Yii2 query all get value in join

I have an database with tablenames like this: tbl_accessoires_1, tbl_accessoires_2 etc. In my main table is a column that gives me the number for the table I have to join. But how do I get this value if I use ->all().
This is my query:
$query = (new Query())
->select([
'a.id id',
'a.soort soort',
])
->from('auto_new a')
->leftJoin('tbl_accessoires_--soort-- acc', 'acc.id = a.id')
->all();
So the a.soort in the select must be at the --soort--
Is there any way to do this?
If I only get one car it is possible because I could get the soort value before this query. but how do I do this when I want to get all cars
So because it's not possible in my situation I've just made a new query to get the options. This will do for now because I don't really need the options when I get all cars.

Get filtered related data without excluding first table rows if there's no related data in second table

Having two related tables, Car and CouponException, I wanna get all cars within an array of models and also get the CouponExceptions related to every Car, but the tricky thing comes here.. i only want to get the CouponException for that car given a coupon id. So what i'm trying now is:
$versions = Doctrine_Query::create()
->from('Car c, c.CouponException ce')
->whereIn('c.model', $models)
->addWhere('ce.coupon_id = ?', $cid)
->fetchArray();
But it only returns to me cars with a coupon exception, and what i want is get all cars in a model list and get the CouponException for that car if there is one with a given Coupon id...
I had to use the LEFT JOIN to get all results and use the "with" keyword to filter the second table.
$versions = Doctrine_Query::create()
->select('c.*, ce.*')
->from('Car c')
->leftJoin('c.CouponException ce WITH ce.coupon_id = '.$cid)
->whereIn('c.model', $models)
->fetchArray();
Now it works :))))

Zend selects all columns

In the following code:
$selectColumns= array('user_id.user_email', // inner join the data from user_id and user_details
'user_details.first_name',
'user_details.last_name');
$result = $handle->select()->from('user_id', $selectColumns)
->where('user_id.uid=?', $uid)
->join('user_details', 'user_id.uid = user_details.uid')
->query(ZEND_DB::FETCH_OBJ);
Zend selects all the columns in the table, not just the requested ones.
How can I select only some?
The problem is in your join() method call:
->join('user_details', 'user_id.uid = user_details.uid')
The optional third argument is columns from this table. If the argument is absent, it defaults to user_details.*.
Note that you added qualified columns from both tables in the from() table, but this has no effect on the default of user_details.*. Sorry, but Zend_Db_Select just isn't smart enough to keep track of all that.
You can make the join() call add no columns by passing an empty array:
->join('user_details', 'user_id.uid = user_details.uid', array())
The qualified columns you added in the from() call should still be there. To verify this yourself, print the SQL:
print $result . "\n"; // calls __toString() method on Zend_Db_Select object
Add another parameter to your join at the end -- an empty array. That will tell it to select no columns from the join. With the code you have now, you are selecting all columns from the joined table.
->join('user_details', 'user_id.uid = user_details.uid', array())

Categories