Join many to one - php

In Codeigniter I am tryign to join two tables with a one-to-many relation. I want to get one result from my table housetype and all of its values/members from other table housetype_member:
$this->db->select('*');
$this->db->join('housetype_member', 'housetype_member.housetype_id = housetype.PkId', 'left');
$result = $this->db->get_where('housetype', array('PkId' => $id));
return $result->result();
So far I get such result:
array (size=2)
0 =>
object(stdClass)[28]
public 'PkID' => string '4' (length=1)
public 'Name' => string 'Classic' (length=7)
public 'image' => string '1449063250.jpg' (length=14)
1 =>
object(stdClass)[30]
public 'PkID' => string '4' (length=1)
public 'Name' => string 'Classic' (length=7)
public 'image' => string '1449063288.gif' (length=14)
First two object values (PkID, Name) are from the first table and the last one (image) is from the second left table. Everything is good but I get an array with two elements, when I only need one housetype object.
Is there a way to write above code so that my returned object would look like this:
object(stdClass)[28]
public 'PkID' => string '4' (length=1)
public 'Name' => string 'Classic' (length=7)
public 'image' =>
array (size=2)
0 => string '1449063250.jpg' (length=14)
1 => string '1449063288.gif' (length=14)
I need one result from the first table and to it I want to join all of its members from the second table.
Can it be done with Codeigniters active record, can it be done at all?

Add group_by() clause to your query.
$this->db->group_by('housetype.PkId');

Related

CakePHP: Load name field of related model on view

Guys I have a simple but boring question...
I have the following scenario:
Solicitation -> HasMany -> Destiny
Destiny -> BelongsTo -> City
My problem is on the view, I want to retrieve the City name instead of the city_id and I can't figure out.
Here is my Result:
array (size=12)
'Solicitation' =>
array (size=32)
'id' => string '25' (length=2)
'Destiny' =>
array (size=2)
0 =>
array (size=3)
'id' => string '3' (length=1)
'solicitation_id' => string '25' (length=2)
'city_id' => string '4382' (length=4)
1 =>
array (size=3)
'id' => string '4' (length=1)
'solicitation_id' => string '25' (length=2)
'city_id' => string '4350' (length=4)
How can I retrieve the city name on the view?
Here's my controller:
public function mySolicitations()
{
$this->Solicitation->recursive = 1;
$person_id = $this->Auth->user('id');
$conditions = array(
'Solicitation.created_by' => $person_id
);
$this->set(array(
'data' => $this->paginate('Solicitation', $conditions, array('Solicitation.id' => 'DESC')),
'title_for_layout' => 'My Solicitations'
));
}
Is there a problem with my relation?
Thanks in advance.
There are two ways:
Change your model recursive value to 2.
$this->Solicitation->recursive = 2;
The drawback of using this is when you have quite a few associations involved, it'll retrieve a lot of unwanted unnecessary data.
You can use "Containable" Behavior here.
$this->Solicitation->Behaviors->load("Containable");
And specify the model names that you want to retrieve:
$this->Solicitation->contain(array(
"Destiny", "Destiny.City"
)
);
Then add your code:
$conditions = array(
'Solicitation.created_by' => $person_id
);
$this->set(array(
'data' => $this->paginate('Solicitation', $conditions, array('Solicitation.id' => 'DESC')),
'title_for_layout' => 'My Solicitations'
));
If you debug, you'll certainly find the "City" index within each Destiny sub arrays.
Hope this helps.
Peace! xD

Join multiple left values with one right value

In Codeigniter I am tryign to join two tables with one to many relation. I want to get one result from my table housetype and all of its values/members from other table housetype_member:
$this->db->select('*');
$this->db->join('housetype_member', 'housetype_member.housetype_id = housetype.PkId', 'left');
$result = $this->db->get_where('housetype', array('PkId' => $id));
return $result->result();
So far I get such result:
array (size=2)
0 =>
object(stdClass)[28]
public 'PkID' => string '4' (length=1)
public 'Name' => string 'Classic' (length=7)
public 'image' => string '1449063250.jpg' (length=14)
1 =>
object(stdClass)[30]
public 'PkID' => string '4' (length=1)
public 'Name' => string 'Classic' (length=7)
public 'image' => string '1449063288.gif' (length=14)
First two object values (PkID, Name) are from the first table and the last one (image) is from the second left table. Everything is good but I get array with two elements, when I only need one housetype object.
Is there a way to write above code so that my returned object would look like this:
object(stdClass)[28]
public 'PkID' => string '4' (length=1)
public 'Name' => string 'Classic' (length=7)
public 'image' =>
array (size=2)
0 => string '1449063250.jpg' (length=14)
1 => string '1449063288.gif' (length=14)
I need one result from first table and to it I want to join all of its members from the second table.
Can it be done with Codeigniters active record?
As far as your second table has multi records with that primary key, it is better if you don't use joins at all.
You can simply get that with two selects.
$this->db->select('PkID, name');
$this->db->where('PkId', $id);
$houseTypes = $this->db->get('housetype')->result();
foreach($houseTypes as $houseType){
$this->db->select('image');
$this->db->where('housetype_id', $houseType->PKId);
$houseType->image = $this->db->get('housetype_member')->result();
}
return $houseTypes;

Doctrine DQL subqueries give a zero result

I have three related entities : Group, GroupDefault, GroupDefaultTranslation on a Mysql server.
The Group entity stores the groups of a user.
The GroupDefault entity define the default groups for any user.
The GroupDefaultTranslation entity stores the translation for the default groups.
The relationships between the entities are types:
- ManyToOne between Group and GroupDefault
- OneToManu ent GroupsDefault and GroupDefaultTranslation
My goal is to display the list of groups of a user with the corresponding translation in his language parameter.
Here is my QueryBuilder with DQL query generated :
public function findByOwnerWithLanguage($languageCode, $ownerId)
{
$qb = $this->createQueryBuilder('g')
->select('g.name')
->addSelect('gdt.content AS name')
->join('g.parent', 'gd')
->join('gd.translations', 'gdt')
->where('g.owner = :owner');
//création de l'expression AND
$orModule = $qb->expr()->andX();
$orModule->add($qb->expr()->eq('g.parent', '0'));
$orModule->add($qb->expr()->eq('gdt.locale', ':language'));
$orModule->add($qb->expr()->eq('g.owner', ':owner'));
//Ajout de l'expression à la requête
$qb->orWhere($orModule)
->setParameter('language', $languageCode, \PDO::PARAM_STR)
->setParameter('owner', $ownerId)
->orderBy('g.isMyLightbox', 'DESC')
->getQuery()
->getResult();
return $qb;
// DQL Query :
// SELECT g.name, gdt.content AS name
// FROM Horyou\Bundle\CoreBundle\Entity\Group g
// INNER JOIN g.parent gd
// INNER JOIN gd.translations gdt
// WHERE g.owner = :owner
// OR (g.parent = 0 AND gdt.locale = :language AND g.owner = :owner)
// ORDER BY g.isMyLightbox DESC
}
And here is the output of the object var_dump :
object(stdClass)[1368]
public '__CLASS__' => string 'Doctrine\ORM\QueryBuilder' (length=25)
public '_em' =>
object(stdClass)[1362]
public '__CLASS__' => string 'Doctrine\ORM\EntityManager' (length=26)
public 'config' => string 'Doctrine\ORM\Configuration' (length=26)
public 'conn' => string 'Doctrine\DBAL\Connection' (length=24)
public 'metadataFactory' => string 'Doctrine\ORM\Mapping\ClassMetadataFactory' (length=41)
public 'unitOfWork' => string 'Doctrine\ORM\UnitOfWork' (length=23)
public 'eventManager' => string 'Symfony\Bridge\Doctrine\ContainerAwareEventManager' (length=50)
public 'proxyFactory' => string 'Doctrine\ORM\Proxy\ProxyFactory' (length=31)
public 'repositoryFactory' => string 'Doctrine\ORM\Repository\DefaultRepositoryFactory' (length=48)
public 'expressionBuilder' => string 'Doctrine\ORM\Query\Expr' (length=23)
public 'closed' => boolean false
public 'filterCollection' => string 'Doctrine\ORM\Query\FilterCollection' (length=35)
public '_dqlParts' =>
array (size=9)
'distinct' => boolean false
'select' => string 'Array(2)' (length=8)
'from' => string 'Array(1)' (length=8)
'join' => string 'Array(1)' (length=8)
'set' => string 'Array(0)' (length=8)
'where' => string 'Doctrine\ORM\Query\Expr\Orx' (length=27)
'groupBy' => string 'Array(0)' (length=8)
'having' => null
'orderBy' => string 'Array(1)' (length=8)
public '_type' => int 0
public '_state' => int 1
public '_dql' => string 'SELECT g.name, gdt.content AS name FROM Horyou\Bundle\CoreBundle\Entity\Group g INNER JOIN g.parent gd INNER JOIN gd.translations gdt WHERE g.owner = :owner OR (g.parent = 0 AND gdt.locale = :language AND g.owner = :owner) ORDER BY g.isMyLightbox DESC' (length=251)
public 'parameters' =>
array (size=2)
0 => string 'Doctrine\ORM\Query\Parameter' (length=28)
1 => string 'Doctrine\ORM\Query\Parameter' (length=28)
public '_firstResult' => null
public '_maxResults' => null
public 'joinRootAliases' =>
array (size=2)
'gd' => string 'g' (length=1)
'gdt' => string 'g' (length=1)
My problem is that the result is zero.
Does anyone see what is the error in my QueryBuilder?
Actually it's not a result - it's just a dump of a query builder object. I think you have to do something like this:
...
$qb->orWhere($orModule)
->setParameter('language', $languageCode, \PDO::PARAM_STR)
->setParameter('owner', $ownerId)
->orderBy('g.isMyLightbox', 'DESC');
$result = $qb->getQuery()->getResult();
return $result;

Join two tables and display distinct list of column

I have three tables.
Candidates
Skills
CandidateToSkillMap
Candidate and Skill tables are mapped in CandidateToSkillMap table. In that candidate_id and skill_id are foreign keys.
How can i get following output with them ?
Assume i need to display Computer Skills of candidate_id = 1
Computer Skills -
MS Word (x)
MS Excel (x)
MS Paint ()
It should display distinct list of all available computer skills and there should be a check-box in-front. It will be checked if specific candidate has that skill.
EDIT -
I have query database and loaded data into arrays -
$candidate_profile_computer_skills
this array gives all the computer skills
array (size=3)
0 =>
object(Candidate\Model\CandidateProfileSkill)[317]
public 'id' => string '1' (length=1)
public 'skill_name' => string 'MS Word' (length=7)
public 'candidate_id' => null
public 'candidateprofileskill_id' => null
1 =>
object(Candidate\Model\CandidateProfileSkill)[223]
public 'id' => string '3' (length=1)
public 'skill_name' => string 'MS Excel' (length=8)
public 'candidate_id' => null
public 'candidateprofileskill_id' => null
2 =>
object(Candidate\Model\CandidateProfileSkill)[316]
public 'id' => string '6' (length=1)
public 'skill_name' => string 'MS Paint' (length=8)
public 'candidate_id' => null
public 'candidateprofileskill_id' => null
$candidate_profile_skills_map
this array returns Skills and CandidateToSkillMap with LEFT JOIN for specific candidate (candidate_id = 1)
array (size=5)
0 =>
object(Candidate\Model\CandidateProfileSkill)[321]
public 'id' => string '1' (length=1)
public 'skill_name' => string 'MS Word' (length=7)
public 'candidate_id' => string '1' (length=1)
public 'candidateprofileskill_id' => string '1' (length=1)
1 =>
object(Candidate\Model\CandidateProfileSkill)[322]
public 'id' => string '2' (length=1)
public 'skill_name' => string 'Sinhala Reading' (length=15)
public 'candidate_id' => string '1' (length=1)
public 'candidateprofileskill_id' => string '2' (length=1)
2 =>
object(Candidate\Model\CandidateProfileSkill)[323]
public 'id' => string '3' (length=1)
public 'skill_name' => string 'MS Excel' (length=8)
public 'candidate_id' => string '1' (length=1)
public 'candidateprofileskill_id' => string '3' (length=1)
3 =>
object(Candidate\Model\CandidateProfileSkill)[324]
public 'id' => string '4' (length=1)
public 'skill_name' => string 'English Reading' (length=15)
public 'candidate_id' => string '1' (length=1)
public 'candidateprofileskill_id' => string '4' (length=1)
4 =>
object(Candidate\Model\CandidateProfileSkill)[325]
public 'id' => string '4' (length=1)
public 'skill_name' => string 'English Reading' (length=15)
public 'candidate_id' => string '1' (length=1)
public 'candidateprofileskill_id' => string '4' (length=1)
A join will do:
SELECT
s.skill_name,
CASE WHEN c.candidate_id IS NOT NULL THEN '(X)' ELSE '()' END has_skill
FROM
skills s
LEFT JOIN CandidateToSkillMap c ON s.skill_id = c.skill_id
WHERE
c.candidate_id = 1
If it joins the right side successfully and thus c.candidate_id will be not null, then it means the person has that skill and you mark it else - don't.
You can just use this
Select S.SkillName, count(*) from CandidateToSkillMap CTS, Skills S where S.Id = CTS.CandidateProfileSkillId group by CV.Id having CTS.CandidateId = 1
SELECT * FROM [Skills] s
LEFT JOIN [CandidateToSkillMap] csm ON csm.candidateprofileskill_id = s.id
WHERE csm.candidate_id = 1
This will return all rows from the skills table, and you can do a null-check on the column "candidate_id" to ascertain whether or not the candidate in question has the skill on that row.
Here's some pseudo:
for($row in $result) {
Skill name: $row["skill_name"]
Has skill?: $row["candidate_id"] != null ? "Yes" : "No"
}
you can try this
select S.skill_name from CandidateToSkillMap CSM, Skills s where S.id=CSM.candidatesprofileskill_id and CSM.candidate_id=1
Try something like
SELECT s.skill_name, (cm.Candidate_id IS NOT NULL) AS HasSkill
FROM Skills AS s
LEFT OUTER JOIN candidateToSkillMap AS cm
ON s.id = cm.candidateprofileskill_id
WHERE s.skill_type = 'Computer Literacy'
AND (Candidate_id = 1 OR Candidate_id IS NULL)
The above query uses LEFT OUTER JOIN to join the skills and candidatestoskillmap include all the rows from skills tables. This will ensure that any rows not matched in the candidatestoskillmap table are included as null values.
The select section then looks for these values and assigns a true/false for it.
The Where section filters for the skill type and the candidate's id.

php array count

I have a var dump of my sql query which return the following
I wanna to count in the array below that how many rows of myID = 5 are there. How would I do that. I am using php. Thanks in advance
array
0 =>
object(stdClass)[17]
public 'myID' => string '5' (length=1)
public 'data' => string '123' (length=3)
1 =>
object(stdClass)[18]
public 'myID' => string '5' (length=1)
public 'data' => string '123' (length=3)
2 =>
object(stdClass)[19]
public 'relativeTypeID' => string '2' (length=1)
public 'data' => string '256' (length=3)
3 =>
object(stdClass)[20]
public 'myID' => string '4' (length=1)
public 'data' => string '786' (length=3)
object(stdClass)[21]
public 'myID' => string '4' (length=1)
public 'data' => string '786' (length=3)
Do you always have the same value of data for the same myID? In other words, is data functionally dependant on myID?
If so, you can get the database to do this for you:
SELECT myID, data, COUNT(*) AS cnt
FROM (your query here)
GROUP BY myID, data
This would give you results like the following:
myID data cnt
'5' '123' 3
'2' '256' 1
'4' '786' 2
Or, you can use a foreach statement, like:
$count = 0;
foreach($arr as $item)
{
// Given that your item is an stdClass Object you access its property with "->"
// if an array $item["myID"] instead
if ( $item->myID == '4' )
{
$count ++;
}
}

Categories