Reputation: 23
I am using php and Mysql to query a database. What i am trying to do is create the following:
Project Name 1
List todo
List todo
List todo
Project Name 2
List todo
List todo
List todo
I have the following mysql tables:
Project
project.projectId
project.projectName
Todo
todo.todoId
todo.todoEntry
todo.todoProjectid
I can query the table and pull through an entire list of projects and left join the todo. BUT, i want to create a header (Project name) and then underneath do the loop.
I could do a nested sql query for each todo based on the parent but that doesnt sound efficient enough to me. Anyone suggest an improvement?
Upvotes: 2
Views: 17217
Reputation: 4063
I made Gordons query a little bit simpler. It now exactly meets your requirements.
SELECT
`name`
FROM
(
(SELECT 'project' as `type`, `name`, `id` as `projectid` FROM `Project`)
UNION ALL
(SELECT 'todo' as `type`, `name`, `projectid` FROM `Todo`)
) as `combined`
ORDER BY
`project_id`, `type`
PHP to get just a list of all rows:
$q = $db->query("SELECT `name` FROM ((SELECT 'project' as `type`, `name`, `id` as `project_id` FROM `projects`) union all (SELECT 'todo' as `type`, `name`, `project_id` FROM `todos`)) as `combined` ORDER BY `project_id`, `type`");
while($row = $q->fetch_object()) {
echo $row->name . '<br />';
}
PHP to get nested lists with 'complicated' query:
$q = $db->query("SELECT `name`, `type` FROM ((SELECT 'project' as `type`, `name`, `id` as `project_id` FROM `projects`) union all (SELECT 'todo' as `type`, `name`, `project_id` FROM `todos`)) as `combined` ORDER BY `project_id`, `type`");
echo '<ul>';
$needToBeClosed = false;
while($row = $q->fetch_object()) {
if($row->type == 'project' AND $needToBeClosed) {
echo '</ul></li>';
$needToBeClosed = false;
}
echo '<li>' . $row->name;
if($row->type == 'project') {
echo '<ul>';
$needToBeClosed = true;
} else {
echo '</li>';
}
}
if($needToBeClosed) {
echo '</ul></li>';
}
echo '</ul>';
But as you can see, the more you try to do in your query. The more PHP is need to use it in a simple way. So you need to find a balance between SQL and PHP to get the nicest code. I would normally not go for the approach above, but just perform multiple queries like this:
PHP to get nested list without 'complicated' queries:
$projects = $db->query('SELECT * FROM `projects`');
echo '<ul>';
while($project = $projects->fetch_object()) {
echo '<li>' . $project->name . '<ul>';
$todos = $db->query('SELECT * FROM `todos` WHERE `project_id` = ' . $project->id);
while($todo = $todos->fetch_object()) {
echo '<li>' . $todo->name . '</li>';
}
echo '</ul></li>';
}
echo '</ul>';
You still need to modify the queries for your own needs (table names and such).
Upvotes: 2
Reputation: 1269773
In this case, you have the same columns coming out from the query. Some are from Project
and some are from Todo
. The challenge is to order them in the right way:
select which, name
from ((select 'Project' as which, name, 1 as ordering, projectid, NULL as id
from Project p
) union all
(select 'List' as which, entry, 2 as ordering, projectid, id
from Todo t
)
) t
order by projectid,
ordering,
id;
Upvotes: 0