I need to select specific set of columns from both the table using propel orm 2.0.0. The equivalent query is as below
select b.name as brand_name, b.grade, d.name as dealer_name, d.number
from brand as b join dealer as d
on d.id = b.dealer_id;
I am struggling where the necessary columns on both the tables have same name but need to join using different column.
Help me with the propel php code and also with proper reference site. The document at official site is not a good tutorial.
This should work, provided you have correctly defined your models.
$rows = BrandQuery::create()
->select(['name', 'grade'])
->joinWith('dealer')
->withColumn('dealer.name', 'dealer_name')
->withColumn('dealer.number')
->find();
Related
I have a table which contains records of a 'widget' many of the columns contain just the Id of a record in a different table. When editing the widget record users are allowed to do a save even if it is incomplete. They can open it later and continue.
The problem I have, is when it is incomplete my query returns nothing because the where clause contain fields which have default 0 in them and there is no match in the other tables. Here is a sample of script which illustrates this problem.
select Client,Make,Model,Shape
from
widget,clients,makes,models,shapes
where
widget.ClientId = '3' and
widget.MakeId = makes.Id and
widget.ModelId = models.Id and
widget.ShapeId = shapes.Id
I am building this query dynamically using PHP so am trying to keep it as simple as possible. All sugestions welcome, thanks.
The problem is that you are using an implicit inner join (implicit meaning that you do the join in the where clause). Inner joins return matching records only, therefore if some of the data are incomplete, no records will be returned.
Use an outer join instead, that return all records from one of the tables in the join and the matching records from the other table (MySQL does not support full outer join, but this is not relevant here anyway).
Based on your description widget table is your main table, so use left join to join all other tables on widget to get the widget even if it is incomplete:
select c.Client, m.make, md.model, s.shape
from widget w
left join clients c on c.id = w.ClientId
left join makes m on m.id = w.MakeId
left join models md on md.id = w.ModelId
left join shapes s on s.id = w.ShapeId
select c.Client, m.make, md.model, s.shape
from widget w
join clients c on c.id = w.ClientId
join makes m on m.id = w.MakeId
join models md on md.id = w.ModelId
join shapes s on s.id = w.ShapeId
Use Joins instead of multiple tables in FROM Clause.
Instead of direct join use LEFT JOIN so that no matter if there is records from other tables, still first table entries will be returned:
SELECT Client, Make, Model, Shape
FROM widget
LEFT JOIN clients ON widget.ClientId = widget.Id
LEFT JOIN makes ON widget.MakeId = makes.Id
LEFT JOIN models ON widget.ModelId = models.Id
LEFT JOIN shapes ON widget.ShapeId = shapes.Id
WHERE widget.ClientId = 3
Table columns should be in lower case
Table names should be in singular form, e.g. model, shape
Foreign keys should be in other table. Instead of widget having ModelId, model should have widget id
I may be wrong if relations are different
I am using Yii2 for my project. I need to "translate" this DAO query into ActiveRecord one. Let me first show you my DAO query, and then my try with Active Record, and then I will specify what I am trying to do. I believe that everything will be clear to you, once you see DAO version.
Here is the DAO version:
return $db->createCommand("SELECT c.id, c.naziv, c.naziv_bih, c.naziv_hr, c.illustration_url,
coc.cpv_id, COUNT(coc.club_offer_id) AS offersCount, TRIM(TRAILING '0' FROM c.id) AS cpvRoot
FROM club_offer_cpv coc
JOIN cpv c ON coc.cpv_id = c.id
JOIN club_offer co ON coc.club_offer_id = co.id
JOIN club_territories ct ON co.club_id = ct.club_id
WHERE ct.teritorije_id = $territory_id
GROUP BY c.id
ORDER BY offersCount DESC
LIMIT 9 ;
")->queryAll();
And this is my try with AR:
return self::find()->select("cpv_id, COUNT(club_offer_id) AS offersCount, TRIM(TRAILING '0' FROM cpv_id) AS cpvRoot")
->with([
'cpv',
'clubOffer',
'clubOffer.clubTerritories' => function ($query) {
$query->andWhere("teritorije_id = $territory_id");
},
])
->groupBy(['cpv_id'])
->limit(9)
->orderBy(['offersCount' => SORT_DESC])
->all();
1) This query will select * from the cpv table, and I want only specific columns: c.id, c.naziv, c.naziv_bih, c.naziv_hr, c.illustration_url.
2) I need to apply this condition WHERE ct.teritorije_id = $territory_id. You can see how I tried to write this in AR, but it does not work, if I look at debugger, this conditions is not in query at all.
3) I need to apply GROUP BY and ORDER BY like you see in DAO version.
4) clubOffer is relation with table club_offer, but I am not selecting anything from it, except that I use it in DAO for joining.
5) clubTerritories is relation of club_offer table with club_territories table. I need it for WHERE part of the query.
What I am doing wrong ? Eager loading is giving me better performance, but I do not understand if I can do same things with it like with JOIN. Can you help we with this problem ? I would like to use AR but I'm having a hard time "translating" DAO into AR. Thanks
The problem is: Query->with() method you are using is not alias for join - you must still use join() if you want to filter results by related tables attribute. with method only creates extra db requests and populates/adds results as AR relations models. If you still need all your ARs including relations in results you may use join for filtering and with for attaching relations both.
I am creating a report and I need to be able to create a query(s) to pull the information below into a report. Essentially here's what I want listed:
ship.name
personnel.first_name
personnel.last_name
crew_position_title.title
personnel_next_of_kin.next_of_kin_relation
personnel_next_of_kin.next_of_kin_first_name
personnel_next_of_kin.next_of_kin_last_name
personnel_next_of_kin.next_of_kin_telephone
personnel_next_of_kin.next_of_kin_alt_telephone
personnel_next_of_kin.other_kin_relation
personnel_next_of_kin.other_kin_first_name
personnel_next_of_kin.other_kind_last_name
personnel_next_of_kin.other_kin_telephone
personnel_next_of_kin.other_kin_alt_telephone
The only condition would be WHERE personnel.currently_serving_ship_id IS NOT NULL on the personnel table.
How would I go about creating a query to give me the data I need? I have tried using JOIN but I don't have much experience with them.
Below is the ERD of the tables I need data from with fields of interest highlighted:
How about something like?
SELECT s.name, p.first_name, p.last_name, c.title, pnk.next_of_kin_relation,
pnk.next_of_kin_first_name, pnk.next_of_kin_last_name, pnk.next_of_kin_telephone,
pnk.next_of_kin_alt_telephone, pnk.other_kin_relation, pnk.other_kin_first_name,
pnk.other_kin_last_name, pnk.other_kin_telephone, pnk.other_kin_alt_telephone
FROM personnel p
LEFT JOIN personnel_next_of_kin pnk ON pnk.personnel_id = p.personnel_id
LEFT JOIN ship s ON s.ship_id = p.currently_serving_ship_id
LEFT JOIN personnel_key_info pk ON pk.personnel_id = p.personnel_id
LEFT JOIN crew_position_title c ON c.crew_pos_id = p.personnel_id
WHERE p.currently_serving_ship_id IS NOT NULL
This is the long version of the query. I am not really sure about this: LEFT JOIN crew_position_title c ON c.crew_pos_id = p.personnel_id. I can't tell what key should be used there, can't figure out using the naming convention.
Query was not tested but you can give it a shot and fix the syntax issue if there are any.
I'm struggling with retreiving data in propel 1.6.7.
Here's the sample of query I want to achieve:
select count(1) as amount, p1.local_id FROM panel_data pd
JOIN panel_data_has_code pp1 on (pd.panel_data_id = pp1.panel_data_id)
JOIN panel_code p1 on (pp1.panel_code_id = p1.panel_code_id AND p1.type='equipment' AND model_id = 'my_model_id')
JOIN panel_data_has_code pp2 on (pd.panel_data_id = pp2.panel_data_id)
JOIN panel_code p2 on (pp2.panel_code_id = p2.panel_code_id AND p2.type='model' AND p2.local_id='my_local_id')
GROUP BY p1.local_id
However whenever I try to construct proper criteria in Propel ORM, I'm having an issue - apparently propel always translate join alias to table name, whenever I try to use add join condition or use alias in select method. I've replaced multiple join condition with simple filterBy method (I always use inner joins, so effect will be the same), but I'm still having issue with retreiving groupped column (p1.local_id).
Here's the code I work with atm:
PanelDataQuery::create()
->select(array( 'p1.localId'))
->withColumn('count(1)', 'amount')
->usePanelDataHasCodeQuery('pp1')->usePanelCodeQuery('p1')->groupByLocalId()->filterByType($type)->endUse()->endUse()
->usePanelDataHasCodeQuery('pp2')->usePanelCodeQuery('p2')->filterByType('model')->filterByLocalId($model)->endUse()->endUse()
->find();
Above statement returns an error:
Unable to execute SELECT statement [SELECT count(1) AS amount, panel_code.LOCAL_ID AS \"p1.localId\" FROM panel_data INNER JOIN panel_data_has_code pp1 ON (panel_data.PANEL_DATA_ID=pp1.PANEL_DATA_ID) INNER JOIN panel_code p1 ON (pp1.PANEL_CODE_ID=p1.PANEL_CODE_ID) INNER JOIN panel_data_has_code pp2 ON (panel_data.PANEL_DATA_ID=pp2.PANEL_DATA_ID) INNER JOIN panel_code p2 ON (pp2.PANEL_CODE_ID=p2.PANEL_CODE_ID) WHERE p1.TYPE=:p1 AND p2.TYPE=:p2 AND p2.LOCAL_ID=:p3 GROUP BY p1.LOCAL_ID] [wrapped: SQLSTATE[42000]: [Microsoft][SQL Server Native Client 11.0][SQL Server]The multi-part identifier \"panel_code.LOCAL_ID\" could not be bound.]
Obviously, select clause causes the problem. Any ideas how to force propel to use table alias instead of translating it to table name?
Thank you in advance for any help.
Found partial solution:
PanelDataQuery::create()
->withColumn('p1.local_id','localId')
->withColumn('count(1)', 'amount')
->select(array( 'localId','amount'))
[...]
Seems to work fine. Altought I'd appreciate any other solutions. Still would be great how to deal with similar problem in addJoinCondition.
When i replace:
->filterByType('model')->filterByLocalId($model)
From the original query, with:
->addJoinCondition('p2', 'p2.localId = ?', $model)
->addJoinCondition('p2', "p2.type = 'model'");
I got similar issue as stated in error: propel translates p2.localId to panel_code.local_id which isn't correct (multiple panel_code table joins with aliases are included in query).
I have the following table structure of my db:
tbl_project
tbl_employee
tbl_deliverable
user_to_deliverable
Where tbl_prjct and tbl_deliverable have a 1-to-many relationship,
tbl_employee and tbl_deliverable have many-many relationships so they are split into user_to_deliverable table.
I want a query to show project_name(from tbl_project), project's deliverables (from tbl_deliverable) and employee name which that specific deliverable is assigned to.
Can I get help writing this query?
Your desired query is much like 89.67% like this :D
SELECT a.ProjectName,
b.deliverables,
d.employeename
FROM tbl_project a
INNER JOIN tbl_deliverable b
ON a.projectID = b.projectID
INNER JOIN user_to_deliverable c
ON b.recordID = c.RecordID
-- or could be the primary key
INNER JOIN tbl_employee d
ON c.userID = d.userID
Approximate solution without knowing your schema. If you want the deliverables/employees concatenated for each project it would probably be best done by retrieving the results and parsing in a non-SQL language (PHP, Python, or whatever you are using). If you want this completely done in SQL you will need to use GROUP_CONCAT().
select tbl_project.name as project,
tbl_deliverable.name as deliverable,
tbl_employee.name as employee
from tbl_project
join tbl_deliverable
on (tbl_project.id = tbl_deliverable.project_id)
join user_to_deliverable
on (tbl_deliverable.id = user_to_deliverable.deliverable_id)
join tbl_employee
on (user_to_deliverable.employee_id = tbl_employee.id)