+-------+------+-----------+------------+
|user_id| name | parent_id |grandparentID
+----+--------+-----------+-------------+
| 1 | one | NULL | NULL |
| 2 | two | 1 | NULL |
| 3 | three | 1 | 1 |
| 4 | four | 2 | 1 |
| 5 | five | 2 | 2 |
| 6 | six | 2 | 2 |
| 7 | seven | 2 | 2 |
| 8 | eight | 3 | 3 |
| 9 | nine | 3 | 2 |
| 10 | ten | 3 | 1 |
| 11 | eleven | 3 | 2 |
+-------------+-----------+------------+
I want to create a tree structure with the following DB schema
Something like this below
One
|
two______________three______________four______________five______________Six
| | | | |
n1 n2 n3 n4 n5 t1 t2 t3 t4 t5 h1 h2 h3 h4 h4 a1 a2 a3 a4 a5 s1 s2 s3 s4 s5
I wrote the following code
<?php
function display_tree() {
$result = $this->qry("SELECT * FROM users WHERE Parent='?' or Parent ='?';" ,
'in(select id from user_id from users where Parent = "'.$_SESSION['id'].'")', $_SESSION['id']);
echo '<div align="center">'.$_SESSION['name'].'<br></div>';
echo '<div align="center">|</div>';
echo '<div align="center">';
while( $row=mysql_fetch_assoc($result)){
echo "___".$row['name'].$row['user_id'].'';
};
$result1 = $this->qry("SELECT * FROM users where grandParent='".$_SESSION['id']."'");
echo '<br>|<br>';
while( $row1 =mysql_fetch_assoc($result1)){
echo "--".$row1['name'];
}
echo '</div>';
}
?>
This is what it displays
one
|
___two___three
|
--four--five--six--seven--eight--
But I wish to have it in the order up above, not this,
I have read tutorials but they all dwell on right left branching, none seems to touch on my type
Any links to good examples, I'll be glad
Any insight on my problem would also help me alot
I seem to have reached a fix end for me
Thanks in advance.
I would recommend using some kind of plugin like jquery plugin that would build the tree for you here are couple of plugins.
http://jquery.bassistance.de/treeview/demo/
http://www.jqwidgets.com/jquery-widgets-demo/#demos/jqxtree/treebindingtojson.htm
https://github.com/pioz/jquery-tree
Related
I have built a membership application that allows users to assemble projects whose contents are contained across 2 tables ('projects' and 'notes'). Each member can create, update or delete as many projects as they want.
Good so far...
I'd like the members to be able to share their projects with other members they choose. At this point I have built a function that allows Member A to type in an email address in order to share a project (with say, Member B). If that email exists in the DB it updates a third table 'sharing' with the project owner's ID (Member A), the "shared_with" member's ID (Member B) and the project ID. (Perhaps I have gone bullheaded in the wrong direction?)
The problem: How do I query the DB to show Member B all of their own projects + any projects that have been shared with them? The query below illustrates the direction I've been which has been useless. I am trying to say, "Select all from projects where user_id = (me) AND all corresponding projects where my ID is in the 'sharing' table under the 'shared_with' column. ...Oh yeah, and grab that project_id in order to know which project while you're at it."
My brain is mush. Any direction would be sincerely appreciated.
function find_all_projects($id) {
global $db;
$sql = "
SELECT *
FROM projects
LEFT
JOIN sharing
on projects.id = sharing.project_id
WHERE user_id = '" . db_escape($db, $id) . "'
OR sharing.shared_with = '" . db_escape($db, $id) . "'
ORDER
BY project_name
";
$result = mysqli_query($db, $sql);
confirm_result_set($result);
return $result;
}
Current Table Structure
From your question I believe your current table structure to be something like the following:
TABLE: user TABLE: project TABLE: shared
id | email | | id | user_id | content | | id | user_id | project_id
---+-------------------- ---+---------+------------------------------ ---+---------+------------
1 | james#website.com | | 1 | 1 | Project for James | | 9 | 1 | 5
2 | hannah#website.com | | 2 | 1 | Some other project for James | | 10 | 3 | 5
3 | lucy#website.com | | 3 | 2 | Project for Hannah | | 11 | 1 | 8
| | | 4 | 2 | A new project for hannah | | 12 | 2 | 8
| | | 5 | 2 | Hannah's pride and Joy | |
| | | 6 | 3 | Lucy cracking down | |
| | | 7 | 3 | Lucy's second project | |
| | | 8 | 3 | Lucy's public stuff | |
SQL
Example: https://www.db-fiddle.com/f/6KnEsGUmy5PS42usmzyTEX/0
SELECT project.id, project.user_id AS owner_id, shared.user_id AS shared_id, project.content
FROM project
LEFT JOIN shared
ON project.id = shared.project_id
AND project.user_id <> ?
WHERE project.user_id = ?
OR shared.user_id = ?;
N.B.
The key difference between this SQL statement and the one in your question is
AND project.user_id <> ?
Without that condition in the ON clause you will get duplicate records for every shared project for that user. I.e. if the user has shared the project with 20 users then there will be 20 duplicates.
This is expected behaviour as explained here: PHP while statement echoes duplicates
PHP
$sql = "
SELECT project.id, project.user_id AS owner_id, shared.user_id AS shared_id, project.content
FROM project
LEFT JOIN shared
ON project.id = shared.project_id
AND project.user_id <> ?
WHERE project.user_id = ?
OR shared.user_id = ?
";
$query = $mysqli->prepare($sql);
$query->bind_param("iii", $user_id, $user_id, $user_id);
$query->execute();
Alternate Table Structure
I suggest updating your table structure so that you have three tables (effectively: users, projects, and project_users). The project_user table then acts as a conduit between the two entities (users and projects). In this case storing the relationship between the two (i.e. owner vs shared with).
TABLE: user TABLE: project TABLE: project_user
id | email | | id | content | | id | user_id | project_id | role
---+-------------------- ---+------------------------------ ---+---------+------------+-----
1 | james#website.com | | 1 | Project for James | | 1 | 1 | 1 | 1
2 | hannah#website.com | | 2 | Some other project for James | | 2 | 1 | 2 | 1
3 | lucy#website.com | | 3 | Project for Hannah | | 3 | 2 | 3 | 1
| | | 4 | A new project for hannah | | 4 | 2 | 4 | 1
| | | 5 | Hannah's pride and Joy | | 5 | 2 | 5 | 1
| | | 6 | Lucy cracking down | | 6 | 3 | 6 | 1
| | | 7 | Lucy's second project | | 7 | 3 | 7 | 1
| | | 8 | Lucy's public stuff | | 8 | 3 | 8 | 1
| | | | | | 9 | 1 | 5 | 2
| | | | | | 10 | 3 | 5 | 2
| | | | | | 11 | 1 | 8 | 2
| | | | | | 12 | 2 | 8 | 2
SQL
Example: https://www.db-fiddle.com/f/imQZ6cvEEff4VgRQ4v22Qo/0
SELECT project.id, project_user.user_id, project_user.role, project.content
FROM project
JOIN project_user
ON project_user.project_id = project.id
WHERE project_user.user_id = ?;
PHP
$sql = "
SELECT project.id, project_user.user_id, project_user.role, project.content
FROM project
JOIN project_user
ON project_user.project_id = project.id
WHERE project_user.user_id = ?
";
$query = $mysqli->prepare($sql);
$query->bind_param("i", $user_id);
$query->execute();
You can use another relationship between members and projects with a table like this :
CREATE TABLE `project_members` (
`project_id` INT NOT NULL,
`member_id` INT NOT NULL,
`is_owner` TINYINT NOT NULL DEFAULT 0,
PRIMARY KEY (`project_id`, `member_id`));
This table allows you to have many members linked to many projects.
The column is_owner is a boolean to easily see if the member is the owner or if the project has been shared to him.
Also it would be good to add foreign keys to project_id and member_id.
I am doing a script want to calculate how many row record before an user record when t1.status is 1.
My table is t1, and the data as below:
+------+---------+------------+----------+----------+
| ID | name | desc | status | time |
+------+---------+------------+----------+----------+
| 1 | ABB | | 1 | 0325 |
| 2 | CCD | | 1 | 0236 |
| 3 | EEF | | 1 | 0325 |
| 4 | GGG | | 1 | 0000 |
| 5 | HIJ | | 2 | 1234 |
| 6 | KKK | | 1 | 5151 |
+---------------------------------------------------+
I was thinking about the query is something like (query row where status = 1 AND stop when reach $userid)
I would like to output to show user (Let's say username is GGG) as:
$userid = 'GGG';
then my output will be
<table><tr><td>Queue: GGG You came in 4 place, in front of you still got 3 person in queue, please be patient</td></tr></table>
How to I do the right query to get the number 4 and 3 ?
Thank you.
You can try something like this hope it helps :-
SELECT count(*) as COUNT FROM t1 WHERE id < (SELECT id FROM t1 WHERE userid = $userid)
I have the tables like this
tbl_post
+-----------+--------------+
| post_id | post_content |
+-----------+--------------+
| 1 | contentone |
+-----------+--------------+
tbl_category
+-------------+---------------+
| category_id | category_name |
+-------------+---------------+
| 1 | Politic |
| 2 | Social |
| 3 | Economy |
+-------------+---------------+
tbl_category_post
+------------------+-------------+---------+
| category_post_id | category_id | post_id |
+------------------+-------------+---------+
| 1 | 1 | 1 |
| 2 | 2 | 1 |
| 3 | 3 | 1 |
+------------------+-------------+---------+
then I want the output like this
+--------------+--------------------------+
| post_content | category |
+--------------+--------------------------+
| 1 | Politic, Social, Economy |
+--------------+--------------------------+
and then how to show the data like this using codeigniter, I really confused at all, anyone please help me!
Edit: With Codeigniter (not tested):
$this->db->select('post_id, GROUP_CONCAT(tc.category_name) AS category_name')
->from('tbl_category_post tcp')
join->('tbl_category tc', 'tc.category_id=tcp.category_id', 'left')
->group_by('tcp.post_id');
I suppose You need PHP loop method to loop this.
Use mysql GROUP_CONCAT function:
SELECT post_id, GROUP_CONCAT(tc.category_name) AS category_name
FROM tbl_category_post tcp
LEFT JOIN tbl_category tc ON tc.category_id=tcp.category_id
GROUP BY tcp.post_id
This is the bookings table I'm using for my query
+----------------------+
| event_id | person_id |
+----------------------+
| 5 | 7 |
| 4 | 7 |
| 3 | 7 |
| 4 | 5 |
| 3 | 5 |
| 5 | 3 |
+----------------------+
This table shows that person_id 7 has 3 bookings, 5 has 2 bookings and 3 has 6 bookings.
Currently, I'm using this query to get the total number of bookings per person.
$query='
SELECT
bookings.person_id,
COUNT(bookings.person_id) AS total,
bookings.event_id,
users.display_name
FROM bookings
INNER JOIN users ON bookings.person_id=users.id
WHERE users.id=bookings.person_id
GROUP BY bookings.person_id';
$result = mysql_query($query);
if($result) {
while($row = mysql_fetch_array($result))
{
/* total bookings per user */
$value = $row['total'];
$sum += $value;
/* events booked per user */
$events....
/* Displaying results */
echo "<tr width='500'>";
echo "<td>".$row['person_id']."</td>";
echo "<td>".$row['display_name']."</td>";
echo "<td>".$row['total']."</td>";
echo "<td>".$events."</td>";
echo "</tr>";
}
This works okay and gives me:
+-----------------------------------+
| ID | NAME | Total Bookings |
+-----------------------------------+
| 7 | Bob | 3 |
| 5 | Jane | 2 |
| 3 | Joe | 1 |
+-----------------------------------+
I'm seeking help to get this to display the events booked by each person (like the 4th columns below):
+------------------------------------------------+
| ID | NAME | Total Bookings | Event IDs |
+------------------------------------------------+
| 7 | Bob | 3 | 5,4,3 |
| 5 | Jane | 2 | 4,3 |
| 3 | Joe | 1 | 5 |
+------------------------------------------------+
Could you please help me getting there.
Thanks.
GROUP_CONCAT https://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_group-concat
$query='
SELECT
bookings.person_id,
COUNT(bookings.person_id) AS total,
GROUP_CONCAT(bookings.event_id) as event_ids,
users.display_name
FROM bookings
INNER JOIN users ON bookings.person_id=users.id
WHERE users.id=bookings.person_id
GROUP BY bookings.person_id';
A bit different query but same result:
SELECT
bookings.person_id,
COUNT(
bookings.person_id
) AS total,
users.display_name,
GROUP_CONCAT(
bookings.event_id
ORDER BY
bookings.event_id
) AS events_list
FROM
bookings,
users
WHERE
bookings.person_id=users.id
GROUP BY
bookings.person_id
ORDER BY
bookings.person_id
I don't know if for a large data, the execution time is less, more or equal.
I have 2 tables, the 'department' and 'document'.
Table department
| doc_id | dept_name |
----------------------------------
| 1 | Information Technology|
| 2 | Software Development |
| 3 | Human Resource |
| 4 | Accounting |
| 5 | Support |
Table document
| doc_id | doc_name | author | description | department |
----------------------------------------------------------------------------
| 1 | Maps | User1 | sample | Information Technology |
| 2 | Audits | User3 | sample | Software Development |
| 3 | Image | User1 | sample | Information Technology |
| 4 | Papers | User4 | sample | Human Resource |
| 5 | Print Screen| User1 | sample | Software Development |
| 6 | Transaction | User3 | sample | Accounting |
| 7 | Graph | User1 | sample | Support |
| 8 | Excel | User1 | sample | Information Technology |
Now, I want to display the table with two columns: department and total_doc.
Output:
| department |total_doc|
-----------------------------------
| Information Technology| 3 |
| Software Development | 2 |
| Human Resource | 1 |
| Accounting | 1 |
| Support | 1 |
I want to display the total document inside the department and arrange them in ascending order.
Here's my query.(not sure)
SELECT department, count(doc_name) as 'total_doc' FROM tbl_document GROUP BY doc_name
I'm using MVC pattern in Codeigniter.
$this->db->select("department, count(doc_name) as 'total_doc'");
$this->db->from('document');
$this->db->group_by('doc_name');
Also, How can I display this in table? like using foreach in html?
You need to do group by with department not with doc_name.
$this->db->select("department, count(doc_name) as 'total_doc'");
$this->db->from('document');
$this->db->group_by('department');
$result = $this->db->get()->result();
Hope This will help you.
foreach ($result as $row)
{
echo $row->department."----".$row->total_doc;
}
here you go
SELECT dept_name,COUNT(td.department) FROM department d
LEFT JOIN tdocument td ON td.`department`=d.`dept_name`
GROUP BY td.`department` ORDER BY COUNT(td.`department`) DESC;
You want one line per department. IN SQL words: You want to group by department.
select department, count(*) as total_doc from document group by department;
(BTW: don't use single quotes for column aliases.)