This question is about selecting data from multiple tables, joins, Doctrine2, ResultSetMapping, DQL and such stuff.
I have 4 tables:
user
contact
contact_phone
call
With relations as shown on the image: http://i.stack.imgur.com/762Jw.png
Every user can have many contacts, each contact can have many phones and each user can have many calls to/from his contacts. Just like in the real world... I've limited the number of fields in each table just for clarity.
So my problem is that I don't know how exactly to map call numbers to contact names when showing a list of calls for a specific user.
If I want to list all calls of user 1 I do:
$callRepository = $this->getDoctrine()->getRepository('MyBundle:Call');
$calls = $callRepository->findAll(array('user' => 1));
But this will give me just the list of all calls for this user and will not associate number (call.number) with names (contact.name).
I can achieve what I want with plain SQL with this query:
SELECT
c.number,
contact.name
FROM
`call` c
JOIN contact_phone cp ON
cp.number = c.number
JOIN contact ON
contact.id = cp.contact_id
WHERE
c.user_id = contact.user_id
AND c.user_id = 1
Please note that I don't want to select all calls (with SQL) and then map numbers to names with another query from the PHP layer because this way I won't be able to search the calls by name for example.
I was thinking that ResultSetMapping could help me in this case but I have no luck putting the SQL query and the ResultSetMapping together.
Please help,
Thanks!
As per my knowledge, you can acheive by using the below methods. Please go to bottom of the page. you can find Joins... try once..
http://docs.doctrine-project.org/projects/doctrine1/en/latest/en/manual/dql-doctrine-query-language.html
Related
I'm developing a system that have a Users table and a Books table.
I need to implement a Users search, and a results page showing all Users and all Books belonging to each user.
Currently, I'm using GROUP_CONCAT to get the Books of each User.
Alternatively, using LEFT JOIN brings duplicate results; Then I have to manipulate the data in PHP(is this 'better'?) Off course, I can't use GROUP BY as I need all Books.
I dont have any problems with GROUP_CONCAT, but now I need to filter by Book's and putting 'WHERE books.name like "% name%"' will filter the GROUP_CONCAT result, then showing just the searched book in the filter(while I need all users books)
Wich is the best method to do a search with One-to-Many results in PHP / MySQL ?
I've been racking my brain all day trying to figure this one out! I'm hoping you guys can help.
I'm building a PHP system which will filter out records for 'Suppliers' within a MySQL table.
The services are stored in a table as such:
id
service
The suppliers are stored in a table as such:
id
company_name
Then after much reading, I added an additional table, which links the suppliers, to their corresponding services:
id
supplier_id
service_id
One supplier can offer many services.
When a user clicks on a filter (span tags which have jQuery on clicks, which capture the id of the service clicked), I want to display the suppliers which offer that service. When a user clicks an additional service, I want to display only the suppliers that offer both of those services. And so on...
I am struggling to establish a) is this the correct way forward, and b) what the SQL would be for it. At the moment, I pass the additional service ID to PHP using $.GET, and store a string of them all as a CSV in Session variables.
Many thanks in advance,
James
is this the correct way forward
Seems sound to me, so far.
what the SQL would be for it
To get the details of all those suppliers that supply both service id 4 and service id 7, you could first join the tables then group them by supplier and filter the resulting groups for those that contain the desired matches:
SELECT p.*
FROM suppliers p
JOIN supplier_services a ON a.supplier_id = p.id
GROUP BY p.id
HAVING SUM(a.service_id = 4)
AND SUM(a.service_id = 7)
To improve the performance of this query, you could throw in a WHERE a.service_id IN (4,7)—this would be particularly beneficial if there is an index on supplier_services(supplier_id, service_id).
I'm trying to understand how to write a query to distinguish if a user has access to certain form or not. I know what I am asking here looks easy but when I tried to implement it, it was whole different thing.
Maybe I am doing it wrong.
Before starting I want to mention the two tables names in start:
sys_forms,
sys_forms_in_groups
Also I am putting a SQL Fiddle link at the end.
Here is what I am trying to do.
If you can see the picture, on top dropdown box (it's a select2 dropdown), user selects the group and it will return GroupID, on the base of which I want to populated the below datatable. (DataTable is just showing groups, it's a dummy, but it will show forms, will fix it if problem is solved)
Now here the problem arise:
I want datatables to show all the forms available in sys_forms table in datatables but in actions columns of datatables only those checkboxes/switches should show granted which are available in the selected group(Group can be selected for select2 dropdown as said before).
GroupID is the column of other table sys_forms_in_groups.
All I want is that all the forms should show in the datatables no matter what group I choose, but Actions column in table should display Granted if the group has access to that particular form.
forms_in_groups is for showing if group has access to that certain form or not. For example:
FormID GroupID
------------------------------
1 1
2 1
1 2
FormID 1 is available to both groupID 1 and 2, on other hand FormID 2 is avaialable only to GroupID 1.
Here is my SQL Fiddle.
Edit
The SQL Fiddle is not working, so putting screenshots here.
Table : sys_forms
Table : sys_forms_in_groups
I have tried this query, but it only returns forms for the selected group, where I want that all forms should show but they must show granted in Actions Columns on checkboxes/switchButtons
SELECT * FROM (`sys_forms`) INNER JOIN `sys_forms_in_groups`
ON `sys_forms_in_groups`.`FormID` = `sys_forms`.`FormID` WHERE `GroupID` = 1;
I think you're, incorrectly, trying to offload the issue onto MySQL.
It's not MySQL's job to render the forms and show whether a selected group has access to a specific form. That will fall onto your rendering of the page; using Select2 in this case.
You just want to retrieve all forms, then show whether the selected group has access to a specific form. That comes down to some Javascript that makes that check for you and displays it properly.
If you want to return all forms, the query would be:
SELECT * FROM (`sys_forms`) INNER JOIN `sys_forms_in_groups`
ON `sys_forms_in_groups`.`FormID` = `sys_forms`.`FormID`;
If you only want the forms that group 1 has access to, the query would be just as you have it:
SELECT * FROM (`sys_forms`) INNER JOIN `sys_forms_in_groups`
ON `sys_forms_in_groups`.`FormID` = `sys_forms`.`FormID` WHERE `GroupID` = 1;
I didn't do a lot of digging into Select2, so I can't really help you in that aspect.
What I can see from your database schema, an inner join is the correct choice here based on the data you are looking for. The only issue I can see is in the WHERE clause. Seems that it may try to look for GroupID in the sys_forms table, so try specifying.
SELECT * FROM (`sys_forms`) INNER JOIN `sys_forms_in_groups`
ON `sys_forms_in_groups`.`FormID` = `sys_forms`.`FormID` WHERE
`sys_forms_in_groups`.`GroupID` = 1;
Finally Problem Solved and working perfectly fine, but after solving that problem i found out there is an other issue i didnt think of, but thats another matter. xD.
However, It was a little rough way to solve but i got what i wanted.
Here is how i did it,
I first needed to update my select query to,
SELECT f.FormID
, f.FormName
, f.FormCIPath
, MAX(g.IsMenuLink) AS IsMenuLink
, GROUP_CONCAT(DISTINCT g.GroupID ORDER BY g.GroupID) AS GroupIDs
FROM `sys_forms` f
JOIN `sys_forms_in_groups` g
ON g.FormID = f.FormID
AND g.GroupID IN (1,2)
GROUP BY f.formID
Here you can see it will return all the forms which belongs to group 1 and group 2 but in a way that 1 and 2 will be in same column separated by comma.
Here how it shows now.
I am not a very complex query master so i am very much grateful to stackoverflow community to help me with the query. As i wanted to join both results to show in comma separated value.
After the MysQL the jquery work was not much difficult, i only sent the group ID for which i wanted the result to show in table. and there i got this result in return where i separate the GroupIDs with javascript split function and i get my groups.
Thankyou again everyone.
I have 3 tables.
users,
campaigns,
links.
They have one-to-many relations. User have many campaigns. Campaign has many links.
I calculate top users by counting the total number of links each user have. So I join 3 tables and group by user and select user and sum(links).
This query involves 3 tables. I have already 3 model class for each of these tables. Now my question is in which model should I put this query? should it go in User model (as I call it top10users? Or there is other way to get this info by utilizing already existing 3 models. I want to know what is most suitable from MVC's point of view.
Additional Information
I am using orm in kohana.
Query:
SELECT u.id,
u.name,
SUM(l.num_visited) total_num_visited
FROM users u
JOIN campaigns c
ON ( u.id = c.user_id )
JOIN links l
ON ( c.id = l.campaign_id )
GROUP BY u.id
ORDER BY total_num_visited DESC
LIMIT 10;
There's no strict reason that your model absolutely has to map 1-to-1 with a table. It may make the most sense in this case to provide a model specifically for Top Users, especially because it is dependent on joining data from several related tables.
Then if there is specific business logic related to Top Users that isn't relevant to the standard User class, you can keep it separated and clean. You can always provide helper / factory methods from TopUser that return instances of User, Campaign, or Link if you need to drill down.
I would say go for topusers(). There is no "correct" answer to this question, not in a technical context. But it should be clearly to understand. So if you want to get top users, why would you put such a method in one of the other models than users? Think of a new team member who gets your code: Where would you look for top users when not in the users model first?
i'm trying to alter drupal view-2 query, basically want to add one more table. I'm able to alter the where clause of query using hook_views_query_alter() but don't know how to join one more table.
function module_views_query_alter(&$view, &$query) {
if ($view->name == 'view1_name') {
$query->where[0]['args'][] = 'SOMETEXT';
$query->where[0]['clauses'][] = "QUERY";
}
if($view->name = 'view2_name'){
$query->table_queue['content_type_sold_product'];
$query->tables['content_type_sold_product'];
}
}
Why do i want to do this - if relationship tab is available in view that is used to join the table, but in my case table which i want to join contains the field that is not a node-reference however field name and its value matches with one of the view table table.
Does anyone know how to perform JOIN in views_query_alter().
Seems there are two different ways you can do this, see these links:
Adding a JOIN statement in hook_views_query_alter()
Add Table Join, Where, and Order By to Views Query in views_query_alter()
Giving Answer to own question
fortunately i found these links
http://drupalmodules.com/module/reverse-node-reference module enhances views with reverse relationships for node reference fields.
you may also need http://drupal.org/project/noderelationships