I'm not sure if this is even possible, or if my JOIN-fu just isn't strong enough(it's pretty wimpy to tell you the truth). I have 3 tables which are tied together with a UID. I'm trying to get information from a result from all of them into one query, except I'm having trouble with making sure the result is what I want.
users
========= USERS ==========
| uid | nickname |
--------------------------
| testusr1 | Test User 1 |
| testusr2 | Test User 2 |
| testusr3 | Test User 3 |
| testusr4 | Test User 4 |
============= GALLERY ===========
| id | uid | ext | profile |
---------------------------------
| 1 | testusr1 | png | 1 |
| 2 | testusr2 | jpg | 1 |
| 3 | testusr3 | png | 1 |
| 4 | testusr4 | png | 1 |
| 5 | testusr4 | jpg | 0 |
============= FRIENDS =============
| sender | reciever | status |
-----------------------------------
| testusr1 | testusr3 | 0 |
| testusr2 | testusr3 | 1 |
| testusr2 | testusr1 | 1 |
| testusr3 | testusr4 | 1 |
What I'm trying to do is get all of a user's friends. Friends are in the friends table where the status = 1. The uid can be either the sender or the reciever. In the table above, testusr3's friends are: testusr2 and testusr4
From here I want to snag the nickname from users, and the id from gallery WHERE profile = 1 AND uid = (that friend's ID).
So far, my query looks like:
$query = "SELECT u.uid AS USERID, g.id, g.ext, f.sender, f.reciever
FROM friends f
LEFT JOIN gallery g ON g.uid = f.sender AND g.profile = 1
LEFT JOIN users u ON u.uid = f.sender
WHERE f.status = 1
AND (f.sender = '$sentuid' OR f.reciever = '$sentuid')";
But, it labels all of the results as f.sender...and I'm pretty sure the g.profile = 1 isn't working. It does grab the friends accurately though. Any help would be greatly appreciated.
Untested Solution
Best place to start is to get the matching records in a single column, with UNION. Then you have all the UIDs you need, in one place.
SELECT f.uid, u.nickname, g.id
FROM
(
(SELECT reciever as uid FROM friends where status=1 and sender='$sentuid')
UNION
(SELECT sender as uid FROM friends where status=1 and reciever='$sentuid')
) f
LEFT JOIN gallery g ON f.uid = g.uid and profile=1
LEFT Join users u ON f.uid = u.uid
Side notes:
Generally a bad idea to use char for an ID field.
For performance reasons, you may be better off actually using more storage space, and doubling up on the 'friends' records. i.e.: two entries for each friendship.
Seems to me that you're really close, but a SQLfiddle would help. I believe you are right, g.profile = 1 is not working because you have no table reference for it, might as well take it out. But because of the join, you should be able to select it.
$query = "SELECT u.uid AS USERID, g.id, g.ext, g.profile, f.sender, f.reciever
FROM friends f
LEFT JOIN gallery g ON g.uid = f.sender
RIGHT JOIN users u ON u.uid = f.sender
WHERE f.status = 1
AND (f.sender = '$sentuid' OR f.reciever = '$sentuid')";
Related
I'm struggling with mysql joins :/
I've multiple tables inside database fe. tasks, users etc.
Table tasks containing tasks with various variables, but the most important - id's of users signed to task (as different roles inside the task - author, graphic, corrector):
+---------+-------------+--------------+
| task_id | task_author | task_graphic |
+---------+-------------+--------------+
| 444 | 1 | 2 |
+---------+-------------+--------------+
Table users
+---------+----------------+------------+-----------+
| user_id | user_nice_name | user_login | user_role |
+---------+----------------+------------+-----------+
| 1 | Nice Name #1 | login1 | 0 |
+---------+----------------+------------+-----------+
| 2 | Bad Name #2 | login2 | 1 |
+---------+----------------+------------+-----------+
Using PDO I'm getting the whole data I want while using INNER JOIN with data from different tables (and $_GET variable)
SELECT tasks.*, types.types_name, warehouse.warehouse_id, warehouse.warehouse_code, warehouse.warehouse_description
FROM tasks
INNER JOIN types ON types.types_id = tasks.task_id
INNER JOIN warehouse ON warehouse.warehouse_id = tasks.task_id
WHERE tasks.task_id = '".$get_id."'
ORDER BY tasks.task_id
Above query returns:
+---------+--------------+--------------+----------------+------------+-----------+------------------+------------------------+------------+-------------+-----------------+-----------+----------------+--------------------+---------------------+-----------+---------------------+------------------+---------------------+
| task_id | task_creator | task_graphic | task_purchaser | task_title | task_lang | task_description | task_description_files | task_files | task_status | task_prod_index | task_type | task_print_run | task_print_company | task_warehouse_code | task_cost | task_time_added | task_deadline | task_date_warehouse |
+---------+--------------+--------------+----------------+------------+-----------+------------------+------------------------+------------+-------------+-----------------+-----------+----------------+--------------------+---------------------+-----------+---------------------+------------------+---------------------+
| 2 | 1 | 2 | 1 | Test | PL | Lorem ipsum (?) | | | w | 2222 | 3 | 456546 | Firma XYZ | 2 | 124 | 29.09.2016 15:48:20 | 01.10.2016 12:00 | 07.10.2016 14:00 |
+---------+--------------+--------------+----------------+------------+-----------+------------------+------------------------+------------+-------------+-----------------+-----------+----------------+--------------------+---------------------+-----------+---------------------+------------------+---------------------+
And I'd like to get query with added user_nice_name after task_creator, task_author and task_graphic - obviously nice names selected from table users based on ID's provide in 3 above fields fe.
+---------+--------------+------------------------------------+--------------+--------------------------------------+
| task_id | task_creator | task_creator_nn | task_graphic | task_graphic |
+---------+--------------+------------------------------------+--------------+--------------------------------------+
| 2 | 1 | Nice Name (from task_creator ID=1) | 2 | Nice Name (from task_graphic ID = 2) |
+---------+--------------+------------------------------------+--------------+--------------------------------------+
How can I achieve that?
You need three joins:
SELECT t.*,
uc.user_nice_name as creator_name,
ug.user_nice_name as graphic_name,
up.user_nice_name as purchaser_name,
ty.types_name, w.warehouse_id, w.warehouse_code, w.warehouse_description
FROM tasks t INNER JOIN
types ty
ON ty.types_id = t.task_id INNER JOIN
warehouse w
ON w.warehouse_id = t.task_id LEFT JOIN
users uc
ON uc.user_id = t.task_creator LEFT JOIN
users ug
ON ug.user_id = t.task_graphic LEFT JOIN
users up
ON up.user_id = t.task_purchaser
WHERE t.task_id = '".$get_id."'
ORDER BY t.task_id;
Notes:
Table aliases make the query easier to write and to read. They are also required because you have three references to users in the FROM clause.
This uses LEFT JOIN for the users in case some of the reference values are missing.
You need to work on your naming. It doesn't make sense that a "warehouse" id matches a "task" id. Or that a "task" id matches a "types" id. But that is how you phrased the query in your question.
The ORDER BY effectively does nothing, because all rows have the same task_id.
Assuming that the task_graphic_name is inside a table name task_graphic_table and the relation field are task_graphic_id
SELECT tasks.*
, types.types_name
, warehouse.warehouse_id
, warehouse.warehouse_code
, warehouse.warehouse_description
, users.user_nice_name
FROM tasks
INNER JOIN types ON types.types_id = tasks.task_id
INNER JOIN warehouse ON warehouse.warehouse_id = tasks.task_id
INNER JOIN users ON users.user_nice_name = tasks.task_graphic
WHERE tasks.task_id = '".$get_id."'
ORDER BY tasks.task_id
And if you need the column appear in a specific order you should explicitally call the column name in sequence eg:
SELECT tasks.col1
, task.col2
, types.types_name
, warehouse.warehouse_id
, warehouse.warehouse_code
, task.col2
, warehouse.warehouse_description
, task_graphic_table.task_graphic_name
Add two sub query in with your query. like
SELECT tasks.*,
....
....,
(select user_nice_name from users where id = tasks.task_author) AS task_creator_name,
(select user_nice_name from users where id = tasks.task_graphic) AS task_graphic_name
FROM tasks
INNER JOIN types ON types.types_id = tasks.task_id
....
....
I have three tables:
// Posts
+----+----------+---------------+-----------+
| id | title | content | id_author |
+----+----------+---------------+-----------+
| 1 | title1 | content1 | 1234 |
| 2 | title2 | content2 | 5678 |
+----+----------+---------------+-----------+
// Users
+----+--------+--------+
| id | name | active |
+----+--------+--------+
| 1 | jack | 1 |
| 2 | peter | 0 |
| 3 | John | 1 |
+----+--------+--------+
// Votes
+----+---------+---------+
| id | id_post | id_user |
+----+---------+---------+
| 1 | 32 | 1234 |
| 2 | 634 | 5678 |
| 3 | 352 | 1234 |
+----+---------+---------+
Now I need to check two conditions before inserting a new vote into Votes table:
The id of author and what I have passed are the same? Posts.id_user = :author (I know I can do that by a FK, but I don't want)
The account of current user is active? Users.active = 1
Also here is my query:
INSERT INTO Votes (id_post,id_user)
SELECT ?,?
FROM Posts p
WHERE p.id_user = :author limit 1;
How can I add second condition Users.active = 1 to my query?
EDIT: Actually I'm trying to don't let people be able to vote who are inactive (active = 0). For example if SO bans men, then I cannot vote to post anymore, because I (current user) am banned. So I'm pretty sure $_SESSION['id'] should be used in the query.
INSERT INTO Votes (id_post,id_user)
SELECT p.id,u.id
FROM Posts p, Users u
WHERE p.id_user = :author
AND u.id = :user
AND u.active = 1 limit 1;
then you set parameter user equal to the current user id.
EDIT: I suppose id_user in table Votes must be the voter's id, not the author of the post (correct?), so I fixed the query eliminating the JOIN.
Use and with where
INSERT INTO Votes (id_post,id_user)
SELECT ?,?
FROM Posts p, Users u
WHERE p.id_user = :author and u.active = 1 limit 1;
INSERT INTO Votes (id_post,id_user)
SELECT p.id, u.id
FROM Posts p
INNER JOIN Users u ON 1 = 1
WHERE p.id_user = :author
AND u.id = :current_user_id
AND u.active = 1
LIMIT 1;
I am developing a photo sharing app platform. The app allows you to post a photo and others can like or rate the photo. Users can follow each other and see photos their 'followings' are sharing, just like instagram.
#user_tbl
id | name | number
-------------------
1 | Dan | 0209
2 | Sam | 2854
3 | Dave | 8123
4 | Alex | 5600
#photo_tbl
id | userid | path
-------------------
1 | 3 | dave-dog.jpg
2 | 1 | dans-cat.png
3 | 4 | alex-bird.jpg
4 | 2 | sam-fish.jpg
#friendship_tbl
id | actor | target
--------------------
1 | 2 | 1 // Sam is following Sam
2 | 2 | 4 // Sam is following Alex
3 | 1 | 3 // Dan is following Dave
4 | 4 | 2 // Alex is following Sam
#activities_stream_tbl
id | photoid | userid | context | date
----------------------------------------------------------
1 | 3 | 4 | add-new-photo | 10/10/2015
2 | 1 | 3 | add-new-photo | 12/10/2015
3 | 3 | 2 | Sam-share-Alex-photo | 15/10/2015
4 | 4 | 2 | add-new-photo | 20/10/2015
6 | 1 | 1 | Dan-like-Dave-photo | 21/10/2015
The #user_table holds the basic info of a user, while #photo_tbl hold the name and path of the photo shared by the user. In the #friendship_tbl is the relationship link between users. "actor" column is the id of the user doing the following while "target" column is the id of the user being followed.
I am currently having problem writing a query string to pull photos of USERX and photos of other users USERX is following and GROUP them by "photoid" in the activities_stream_tbl and ORDER BY "date" activities_stream_tbl.
I will be glad if anyone can help me, show me a better way of structuring db thank you.
to pull photos of USERX, you can construct your sql like
select PATH
from user_tbl as a inner join photo_tbl as b
on a.id = b.user_id
and a.name = 'userx'
and to pull photos of other users USERX is following, you may write
select path
from photo_tbl as a
where a.userid in (select target from friendship_tbl as x inner join user_tbl as y on x.actor = y.id and y.name = 'user')
you can union the above two results if you want.
ex:
select PATH
from user_tbl as a inner join photo_tbl as b
on a.id = b.user_id
and a.name = 'userx'
UNION
select path
from photo_tbl as a
where a.userid in (select target
from friendship_tbl as x
inner join user_tbl as y
on x.actor = y.id and y.name = 'user')
I have a following system where users can follow each other and search for users to follow. Here are examples of the users and following tables:
Users Table:
+-------+-----------+
| id | userName |
+-------+-----------+
| 1 | John |
| 2 | Harriet |
| 3 | Chris |
| 4 | Lisa |
| 5 | Joe |
+-------+-----------+
Following Table:
+-------+-------+-------+
| id | id_1 | id_2 |
+-------+-------+-------+
| 1 | 5 | 3 |
| 2 | 1 | 2 |
| 3 | 1 | 5 |
| 4 | 5 | 4 |
+-------+-------+-------+
I want to know how to structure a mySQL statement to join the following table with the users table where the username is like '%$search%' to return all results of this occurrence (i.e. searching 'jo' returns John and Joe) and when there are multiple results for each person (i.e. Joe will occur twice in Following) return only results where id_1 is the current logged in users id to show that the logged in user is already following this person.
$search = $_POST['search'];
$userid = $_POST['userid'];
$qry = "
SELECT u.id
, u.userName
, f.id_1
, f.id_2
FROM users u
LEFT
JOIN following f
ON IF('$userid' = f.id_1, u.id = f.id_2, u.id = f.id_1)
WHERE u.userName LIKE '%$search%';
";
This query returns every occurrence of the username in the following table but it should only return once.
Any help would be great.
Thanks.
Not absolutely sure but give it a try
SELECT u.id
, u.userName
, f.id_1
, f.id_2
FROM users u
LEFT JOIN following f
ON u.id in (f.id_1,f.id_2)
AND f.id_1 = '$userid'
WHERE u.userName LIKE '%$search%'
ORDER BY u.id
LIMIT 1;
Since I'm very new don't judge me. I am trying to make a filter but there are some difficulties on the way. I have two tables of data. First with companies, second with users.
Companies:
____________________
id | name |
1 | try |
2 | test |
3 | experiment |
Users:
_____________________________________
|id | company_id | name | status |
| 1 | 1 | Idiot |pending |
| 2 | 1 | Funny |active |
| 3 | 2 | Me |pending |
| 4 | 2 | Lucky |rejected|
| 5 | 2 | Moon |rejected|
I have to make perhaps INNER JOIN and take only companies and users that are pending. I'm not interested in 'rejected'. So I'm interested to get:
3 | 2 | Me | pending | test
and other record with pending and no active. The company must have pending user and the same company must not have active.
SELECT *
FROM users u
INNER JOIN companies c
ON u.company_id = c.id
WHERE u.status = 'pending'
AND NOT EXISTS(SELECT u2.status
FROM users u2 ON u2.id = c.id
WHERE u2.status = 'pending')
or something like that was the SQL but I can't check it now. I want to make it Doctrine
e.g. $query = ..->innerJoin(..)->where... but can't make it. Any help please. Oh and how would this handle 100,000 records database for example? Is there a better way? Thank you.
in /lib/model/doctine/UsersTable.class.php:
class UsersTable extends Doctrine_Table
{
public function getAllCompanies($user_id) {
$q = $this->createQuery('u')
->where('u.istatus = ?','pending')
->leftJoin('u.Companies c WITH c.id = u.company_id')
->execute();
return $q;
}
}