Select many relational ID in one shot(MYSQL) - php

so we have:
table users
id name password parent_id
the first user have the id 1, and others have the parent_id 1, so I select all the users that have the parent_id == 1 - they are the childs of the user with 1, okay its all right, but now i need to select the users that have the parent_id of the selected before users with they id, if they exists of course
user with id 1
/ | \
/ | \
/ | \
users with parent_id 1
user id 2 user id 3 id user 4
| | |
| | |
| | |
and here is the same, I need to select all the users that have the parent_id 2, 3, 4 for each of those user, its is something like a pyramide(triangle) from the top to the bottom
So the question is how can i make a query that will select it in one shot, not in many queries by extracting the id and then make other query - its not good i think
do you have an idea??

Here is a question, that covers your problem:
Is it possible to query a tree structure table in MySQL in a single query, to any depth?
Query below works only for finding children and grand-children of a single user and is a product of misunderstanding the question!
You could try joining user table on itself twice.
SELECT * FROM users as up
JOIN users as u on up.id=u.parent_id
JOIN users as uc on u.id=uc.parent_id
WHERE up.id={$grandParentUserId}
Aliases: up = user's parent, u = user, us = user's child.
Definitely not a pretty solution, but it's a single request.

I see you are using CI. You can have a look at this answer. Somewhat related to your question. You can select the users with NULL parent ID first and then populate their children
https://stackoverflow.com/a/9937130/876117

Related

MySQL Duplicating Row Results in Table When Searching Across Multiple Tables

I have three tables in a mySQL db one for users, one for colours and one for the linking of the users to the colours
Table 1 users
==============
ID | Name
--------------
1 | John
2 | Jayne
3 | Fred
Table 2 colours
==============
ID | Colour
--------------
1 | Blue
2 | Red
3 | Yellow
Table 3 link
==============
ID | Name | Colour
--------------
1 | 1 | 1
2 | 1 | 2
3 | 2 | 1
4 | 3 | 2
5 | 3 | 3
As you can see, some users have more than one favourite colour (yeah, i know, how annoying).
At the moment, I can show them in a table, with their favourite colour(s) in a column.
BUT, I want to be able to filter the table results by colour.
I can do it no problem with having a filter of just one colour, BUT the problem comes along with two colours.
If I want to see which user has selected for example Blue AND Red, I get a result of zero.
How can I get this result, without creating a search which results in each row being dedicated to a colour and then in turn showing the same user twice (one for red one for blue).
I hope this makes sense
THANKS IN ADVANCE
EDIT
An example query I have used is
SELECT * FROM users, colours, link WHERE users.id = link.name AND link.colour = colours.id
Alternatively to show for specific colour
SELECT * FROM users, colours, link WHERE users.id = link.name AND link.colour = colours.id AND link.colour = 1
But for double filter which shows duplicates
SELECT * FROM users, colours, link WHERE users.id = link.name AND link.colour = colours.id AND link.colour = 1 OR link.colour = 2
If that looks right here is the code:
SELECT Name FROM users
WHERE ID IN (SELECT DISTINCT(Name) AS Name
FROM link L
WHERE 2 IN (SELECT Colour FROM link L2 WHERE L.Name = L2.Name)
AND 1 IN (SELECT Colour FROM link L2 WHERE L.Name = L2.Name))
And now let me try to explain what L and L2 are... First sorry for my English I'll do my best to make a sense for you...
We make subquery on the same table here so we need to use alias for the table. Alias we use to give temporary name table or column which will be used only for that query.
Example for alias is when we select some column from table (Price and Quantity) and let's say we want to calculate Price * quantity and SELECT that column as total (total will be the name of that column in table which we return after we execute the query). Column name total well be give alias. we crate alias like:
SELECT Price, Quantity, (Price * Quantity) AS **total**
FROM t1...
That will return table with three column Price, Quantity, Total... if we don't use this AS total the name of that column will be Price * Quantity...
So here we use L and L2 just to know which column Name is from which part of SELECT query. If we wouldn't use alias in subquery
SELECT Colour FROM link L2 WHERE L.Name = L2.Name
we would have problem because subquery which locks like this:
SELECT Colour FROM link WHERE Name = Name
Doesn't make a a lot of sense, isn't it?
So basically we temporary rename table in this query because we need to know which column from which table we compere whit other one, in other way database will have a problem what to select...
I hope this make a sense for you. If you have any further question fill free to ask I will do my best to try to explain it to you.
I hope i didn't make it more complicated than it is...
GL!
EDIT
Hi there again, i worked something and and i figured out that your question probably have better answer than the first i give you... Hope it's not too late!
SELECT u.Name
FROM users u
INNER JOIN link L
ON u.ID = L.Name
INNER JOIN link l2
ON L.Name = L2.Name
WHERE L.Colour = 2 AND L2.Colour = 1
Look SQL Fiddle for that...

Filter MySQL records between two tables by Join depending on a specific column value

Recently I've been working on a PHP/MySQL script which reads information from a database with user info and file info stored in two separate tables.
Below are the schema's for the tables.
Table1
UID | Username | PermissionLevel
1 | First | 1
2 | Next | 3
3 | More | 2
Table2
FID | Filename | FileLevel | UploadUsername
1 | file.txt | 2 | First
2 | hand.mp4 | 1 | First
3 | 1245.dds | 1 | Next
4 | beta.sql | 3 | More
For the purpose of this message I have omitted the passwords column and the file title/description column, since they play no part in the result I am trying to achieve.
So far I have come up with this SQL code
SELECT DISTINCT table2.*,
table1.*
FROM table2 JOIN table2 ON table2.FileLevel <= table1.PermissionLevel
WHERE table2.UploadUsername = table1.Username
ORDER BY FID DESC LIMIT 7
This generates the appropriate listing I want, but does not filter the level of content shown.
Any user with a PermissionLevel of 1 should only see Files with a FileLevel of 1. Users with PermissionLevel of "2" can see files of FileLevel of both 2 AND 1, and so on.
But at the current stage it seems to just want to display ALL results regardless of File/Permission Level.
I've been stuck at this issue for a couple of days now and just can't seem to get my head around this.
It's likely to be something simple I may have overlooked, but I hope that a fresh pair of eyes may help me.
I'm not sure if I understand the question fully, but this is what I could make of it. You have a query that returns all uploaded files. You now want to filter that list, so it sometimes shows less results, depending on the user's permission level. Please note that this user is the active user on the website, who is not necessarily the same user who uploaded a file, so this condition does not work on the table1 table of your query.
A common solution to this is to have a session variable storing your current user's id, and possibly other information.
$_SESSION['user'] = 'somebody';
$_SESSION['permissionLevel'] = 3;
If you don't have permissionLevel in a local variable, you will have to join on the table1 table twice, once to find the uploader and once to find the permission level of the current user. You also have a typo in your original query. The following will give you both users
SELECT *
FROM table2
JOIN table1 uploader WHERE table2.UploadUsername=table1.Username
JOIN table1 currentuser WHERE table2.PersmissionLevel<=table1.PermissionsLevel AND users.Username='$_SESSION[user]'
ORDER BY FID DESC

fetching multiple usernames from a database

I have a comments section on a website i'd like to streamline a bit if possible so it's not as much of an impact on the database. When a user selects a post, and if it has comments associated with it, it lists the comments. when the comments list, it fetches the username from another table. I store the id for the user in the comments table, and use that id to select the record from the users table. and displays as "user" said:
lets say i have 1000 comments on a post, it will hit the users table 1000 times to grab user names. I think this is probably a bad design. i thought of a few solutions, but don't know what would be recommended in this situation.
should i just be storing the username inside the comments table?
should i store all of the usernames already called in a session array?
put all of the usernames in a file, and call from the file?
or is there another solution that i haven't thought of?
i'm kind of confused. I thought i was doing the right thing by using the IDs in the comment table, and then using it to fetch the username, but after reading about a million posts on using less impact on the database, i'm starting to question myself.
WOW, thanks for all of the useful answers. here is the table scheme, i don't know why i didn't put in in originally.
comments table for jokes:
id | author_id | joke_id | date_created | body
---+-----------+---------+--------------+-----
1 | 3 | 2 | 2011-06-12 | this is a comment
and for the users:
id | user_name | password | email | date_joined | visible
---+-----------+----------+-------+-------------+---------
3 | booboo | password | email | todays_date | 1
This is what JOINs are for - so that you can run a single query and efficiently get the combined information from multiple tables. E.g.:
SELECT comments.id, comments.content, users.name
FROM comments
JOIN users ON comments.user = users.id
WHERE comments.id in (1,2,3)
would look up the 3 comments with id 1, 2, and 3, plus also get the username of each commenter, and return rows that looked like this:
comments.id | comments.content | users.name
------------+-------------------+---------
1 | "First comment." | "Poster1"
2 | "Second comment." | "Poster2"
3 | "Third comment." | "Poster3"
It sounds like you have a userID field in your comments table, but need to look up the username, correct? If so, a JOIN would be the best solution.
Something like:
SELECT *
FROM `comments`
LEFT JOIN `users` ON `users`.`id` = `comments`.`userid`
WHERE `postid`='1'
To read more on joins and their endless possibilities, read up here
SELECT * FROM comments LEFT JOIN users ON comments.posterid = users.id
Google for LEFT JOIN for more info :)
Do you allow the same username to be used more than once? If not, then I would use the username field as the PK of your users table and store that in the commentstable as the FK. That'll solve your issue nicely.
If changing the PK of your users table is too much of an issue, then just store the username in the comments section since you can still use that select a single record from your users table.

Nested or Joins query for MySQL using PHP

I have many a times tried using nested query for MySQL in PHP, but it does not work. Is it not possible to do nested/Joins queries?
Just a Scenario:
I have two tables one table with user id and the other with data. User logins and with sessions I have to cross check two different tables with user id (user and data). Is it not possible to nest/join these two tables to write a single query statement.
In short is nesting or joining two or more tables permitted in PHP coding?
YES, it is possible to join two or more tables in MySQL (and therefore, also when using PHP).
You need to post your table schema, if you want us to show a relevant join query. You could, however, try something like:
SELECT * FROM user AS t1
CROSS JOIN data AS t2
ON t1.userid=t2.userid
WHERE t1.userid='154'
(This query presumes that there always will be one row with the userid in both tables. You should use LEFT JOIN instead of CROSS JOIN to return a row even if there is no row in data for the userid. 154 is just an example userid.)
Have a look at http://dev.mysql.com/doc/refman/5.5/en/join.html for information on the JOIN syntax.
users
| user_id | username | password | enabled |
|---------|----------|----------|---------|
| 1 | john | sgsd2gg | 1 |
| 2 | jane | sdshdhd | 0 |
users_data
|udata_id| user_id | some_column |
|--------|---------|-------------------|
| 1 | 1 | Some title |
| 2 | 2 | another title |
Since you haven't posted your table schema, I can't give you an exact solution. But supposing you have a users table and a users_data table, where users_data are owned by a user. You can do a join on the table to retrieve all the data.
SELECT * -- Don't select all fields unless you need it
FROM users U LEFT JOIN users_data UD ON U.user_id = UD.user_id
WHERE U.user_id = 1
This would pull all the records for user with an ID of 1. This is a very simplistic join, but it should give you an idea.
Here's an example that visually describes the different options you can use : SQL Join Differences

Retrieving "likes" tied to users from a database

I'm new to database structure. I'm trying to create an app that allows users to like certain entries, but I want to be able to tie likes to users so that I can change the visuals before/after the like action.
I think from research that I should have an 'entries' and 'users' table and then have a 'likes' table that ties the two to each other.
The only thing I'm unsure of is, when getting and displaying the contents... how would I write the queries? If I query for all the entries I need, do I then go back and individually query each to see if it has a like tied to it for the current user? That seems like it might be a costly operation. Is there a more efficient way?
Hope that makes sense,
Thanks.
I think you have the right database design in mind. As far as queries are concerned, assume tables as such:
Users
ID | Name
1 | Bob
2 | Sally
Entries
ID | Name
1 | Red
2 | Blue
3 | Yellow
Likes
UserID | EntryID
1 | 1
1 | 2
2 | 2
2 | 3
So we can say Bob likes Red and Blue while Sally likes Blue and Yellow. So a query to retrieve all entries, plus an indicator of what Bob likes would be:
SELECT
e.ID,
e.Name,
l.UserID
FROM Entries e LEFT JOIN Likes l ON l.EntryID = e.ID
WHERE l.UserID = 1 -- Bob's User ID
ORDER BY e.Name
This would return
ID | Name | UserID
2 | Blue | 1
1 | Red | NULL
3 | Yellow | 1
The UserID column indicates if Bob likes the entry or not - a NULL is No and a value is Yes.
Assuming you have a table Entries with a column entity_id (and whatever else you store about the entity) and a second table UserLikes that contains the columns user_id and entity_id, you would do the following:
SELECT Entries.col1, Entries.col1 . . ., UserLikes.user_id
FROM Entries LEFT OUTER JOIN UserLikes ON
Entries.entity_id = UserLikes.entity_id
WHERE UserLikes.user_id = :user_id
AND Entity.col_whatever = :whatever
In this example, Entries.col1, Entries.col2 . . . is the list of columns you want to get back about the Entries. The :user_id is a parameter that contains the id of the user you're currently trying to display Entries for. And the last line is standing in for whatever limitations you want to put on the Entries are returned.
This query will give you a row for each Entry you searched for. You can check the value the returned column user_id. If it's NULL then it was not liked by the user, if it contains the user's id, it was liked by the user.
I think u can retrieve the entries and query the likes table at the same time to get if the current user likes the entry performing a stored procedure. So u can control the value of the set of data returned by the query for example returning one colum for the entry text and one boolean column to evaluates the current user likes... In this way you will at least one parameter for the stored procedure to indicate who is the current user
I hope this idea help u...

Categories