i have two tables in my database. table A is USERS and table B is relations, and the following are their columns
USERS(username, avatar, specialty) and RELATIONS(username1, username2, reldir)
RELATIONS stores the relationship between users, that is if, username1 is following username2, reldir = F, and if they are both following each other, reldir=FB and vice versa, this part has worked very well but
i need to query these tables so that i return a list of users from USERS which for example user A doesnt follow but have the same specialty as A...
i tried this, but its not working well ...
$spec = the specialty of user A
SELECT a.username, a.avatar, a.specialty FROM users a, relations b WHERE a.username!=b.username2 AND (b.reldir!='F' OR b.reldir!='FB') AND a.speciality ='$spec'
the query to me seems logically correct but i could be wrong. i need help
You need to add some keys for your tables, because you have two different tables and they doesn't linked.
For example, table USERS:
id (as primary_key), username, avatar, specialty
Table RELATIONS:
user_id, username2, reldir
user_id - it is field "id" from table USERS (instead your "username1")
Then you will be able create a query like this:
SELECT a.*
FROM users a, relations b
WHERE a.id = b.users_id
AND (b.reldir != 'F' OR b.reldir != 'FB')
AND a.speciality = '$spec'
ps: if I understood your question in the right way)
Related
I have two tables:
employees:
id, CMS_user_id, practice_group_id, ...
and
users:
id, level, ...
I want to select all employees where practice_group_id is 2 but only if the respective user has a level of 1 according to the users table. I researched and I have a feeling it has something to do with the UNION keyword eventually, but I can't quite figure it out.
In "human language", the query would be like this:
"select all from employees where practice_group_id is 2 and then check the CMS_user_id from the employee and check in the table users whether the respective user with the id that equals CMS_user_id has a level of 1"
A JOIN will match the corresponding rows between two tables. Then, filtering can be done using WHERE.
For example:
select e.*
from employees e
join users u on u.id = e.CMS_user_id
where e.practice_group = 2 and u.level = 1
Members is a table of persons who are members of a club. Various details of each member are included in this table through various columns such as ID, name, address, email, etc.
Now, any two members of this table can have a relationship. For example, if A, B, C, and D are all members of this table, then A and B can have a relation; A can C have a relation; B and D can have relations, etc. So, while member A can have a relation with all other members (such as B, C, and D, etc.), he can have a relation with any other member in, either way, i.e., it can be A-B or B-A.
For this relationship, a new table Relations has been created. This has only 3 columns; namely, ID, FirstMemberID, SecondMemberID. Here, both FirstMemberID and SecondMemberID are basically the respective IDs of members (in a relationship) from the Members table.
Now, I want to construct an SQL query (for MySQL) to select full details (all columns) from the Members table for all those members who have a relationship with a person with ID of XYZ in such a manner that XYZ is the first part of this relationship. Here XYZ is only the ID of the person and not his name.
So, I can this first query:
SELECT SecondMemberID FROM Relations WHERE FirstMemberID = XYZ;
This query gives multi-results because XYZ has relations with many members.
The other select statement is like this:
SELECT * FROM Members WHERE ID = SecondMemberID;
[Note: Here, SecondMemberID is what is returned from the first query. But, as I said, there can be many SecondMemberID here.]
My problem is how to combine the two queries in such a way that I get proper results.
I have tried various methods, like treating the results of the first query as an array and then using IN operator in the second query by using the implode method of PHP or otherwise. I have also tried various JOIN statements but without success.
What am I missing? Can you please help?
Try
SELECT Members.*
FROM Relations LEFT JOIN Members
ON (Relations.SecondMemberID=Members.ID)
WHERE Relations.FirstMemberID = XYZ;
You need a simple JOIN command in SQL. JOIN joins two tables. INNER JOIN joins them on a specific condition, i.e. concatenates two rows (one from each table) that match the condition. Condition is usually something like: table1.field1 == table2.field2 or you can use LEFT or RIGHT JOIN which will, in turn, join two rows but the right or left one can be empty.
I think you want:
SELECT SecondMemberID
FROM Relations
WHERE Id IN (SELECT SecondMemberID
FROM Members
WHERE FirstMemberID = 'XYZ');
I have 3 tables, where is the first one for user. In another two I have id_user, for product who created or activation who created. How I can show all data from these two tables with both username? I figure out how to join 2 tables, but third I have join twice and I don't know how. This is example for two tables:
$query=$this->db->select('*')
->from('activation')
->join('products','products.id_pro = activation.id_pro')
->order_by('id_key','DESC')
->get();
Table activation has column user_a with user id, and product has column user_p with user id. Sometimes is same user sometimes not. Any helps?
Heres how I do it using aliases. You can format it your way too.
$this->db->select('tb1.*,tb2.*,u.*');
$this->db->join('table1name tb1','tb1.id = u.tb1_id');
$this->db->join('table2name tb2','tb2.id = u.tb2_id');
$this->db->order_by('u.id_key','DESC');
$result = $this->db->get('User u')->result();
If you want to alter between left and right join just add 'left' or 'right' to the join function.
$this->db->join('table1name pr1','pr1.id = u.tb1_id','right');
$this->db->join('table2name tb2','tb2.id = u.tb2_id','right');
This would preference your user table.
I've currently got two tables:
mems (members):
id,
name,
email,
password,
salt,
achievements_id
achievements:
id,
achievement,
description,
points
I am able to correctly display the data for a user with:
"SELECT * FROM achievements WHERE id IN (SELECT achievements_id FROM mems WHERE name = '$name')";
My question is, how do I add the achievement ID to the user so each user has their own achievement records? Currently if I use an update it just wipes over the old achievement so it only ever displays 1 record.
Say I have 2 achievements and 2 users
User 1 achieves achievement 1, it's viewable and they have achievements_id set to 1.
User 2 achieves achievement 1, it's viewable and they have achievements_id set to 1.
User 1 then achieves achievement 2, it's viewable but now they have achievements_id set to 2.
I have no clue how to do this. I know what I want to do, but no clue how to design the database to have each user having their own records of achievements.
I originally did it where achievements table had a member_id and I'd concat the other users ID into their, dodgy but it semi-worked.
Any help? Sorry if I am making no sense.
It sounds like what you need is to model a many-to-many relationship (many users can share the same achievement - ie. be linked to the same entitiy in the achievements table; while a single user can have multiple achievements). This is usually done using an extra table. Let's call it: Members_Achievements_Map.
CREATE TABLE Members_Achievements_Map (
MemberID,
AchievementID
)
This table would link entities from the members table to entities in the achievements table.
The way I would go about this would be to create another table to hold the users achievements.
So basically another table that looks like such:
UserAchievements:
userID, achievementID
That way you can join the tables like:
SELECT * FROM achievements a
INNER JOIN userAchievements uA ON uA.achievementID = a.id
INNER JOIN users u ON uA.userID = u.id
That will give you all the users for all the different achievements.
Hope that helps!
The site I'm working on has 3 different types of users: admin, applicants, reviewers. Each of these groups will have some basic info that will need to be stored (name, id, email, etc) as well as some data that is unique to each. I have created a users table as well as a table for each of the specific groups to store their unique data.
users: id, f_name, l_name, email, user_type
users_admin: id, user_id, office, emp_id
users_applicant: id, user_id, dob, address
users_reviewer: id, user_id, active_status, address, phone
If a user with user_type of "1" (applicant) logs in I will need to JOIN to the users_applicants table to retrieve their full record. I tried using a UNION but my tables have vastly different columns.
Is there a way to, based on a user's type, write a conditional query that will JOIN to the correct table? Am I going about this completely the wrong way?
Thank's in advance for your help!
Well, in the end your tables are already flawed. Why even have a table for each type? Why not put all those fields into the users table, or maybe a user_details table (if you really want an extra table for non-general data fields)? Currently, you're actually creating 4 independent user tables from a relational point of view.
So why do the type-tables have a surrogate key? Why isn't the user_id already the (only) primary key?
If you changed that, all you would need is the user id to retrieve the data you want, and you've already got that (or you wouldn't even be able to retrieve the user type).
Either you do it programmatically, or you can do this with a series of CASEs and LEFT JOINs.
For simplicity's sake let's do this with a table users where you can have a user of type 1 (normal user), 2 (power user) or 3 (administrator). Normal users have an email but no telephone, power users have an address and a field dubbed "superpower", and administrators have a telephone number and nothing else.
Since you want to use the same SELECT for all, of course you need to place all these in your SELECT:
SELECT user.id, user.type, email, address, superpower, telephone
and you will then need to LEFT JOIN to recover these
FROM user
LEFT JOIN users_data ON (user.id = users_data.user_id)
LEFT JOIN power_data ON (user.id = power_data.user_id)
LEFT JOIN admin_info ON (user.id = admin_info.user_id)
Now the "unused" fields will be NULL, but you can supply defaults:
SELECT
CASE WHEN user.type = 0 THEN email ELSE 'nobody#nowhere.com' END AS email,
CASE WHEN user.type = 1 OR user.type = 2 THEN ... ELSE ... END as whatever,
...
Specific WHERE conditions you can put in the JOIN itself, e.g. if you only want administrators from the J sector, you can use
LEFT JOIN admin_info ON (user.id = admin_info.user_id AND admin_info.sector = 'J')
The total query time should not be too bad, seeing as most of the JOINs will return little (and, if you specify a user ID, they will actually return nothing very quickly).
You could also do the same using a UNION, which would be even faster:
SELECT user.id, 'default' AS email, 'othermissingfield' AS missingfieldinthistable,
... FROM user JOIN user_data ON (user.id = user_data.user_id)
WHERE ...
UNION
SELECT user.id, email, 'othermissingfield' AS missingfieldinthistable,
... FROM user JOIN power_data ON (user.id = power_data.user_id)
WHERE ...
UNION
...
Now, if you specify the user ID, all queries except one will fail very fast. Each query has the same WHERE repeated plus any table-specific conditions. The UNION version is less maintainable (unless you generate it programmatically), but ought to be marginally faster.
In all cases, you'll be well advised in keeping updated indexes on the appropriate fields.
Instead i will suggest you reconstruct you tables structure like this.
Create a table
users_types :
id
type
Then create another table users with a foreign key
users :
id
f_name
l_name
email
office
emp_id
dob
address
active_status
phone
users_types_id
And now when you need to insert data insert null in the fields which are not required for a particular user. And you can simply fetch records on the basis of id. Also using left join will give you the name of user type.