I have this query that uses a UNION:
$this->db->query('
SELECT DISTINCT users.user_pic, users.id, users.username, contacts.accepted
FROM users
LEFT JOIN contacts ON users.id = contacts.user_1
WHERE contacts.user_2 = ' . $this->session->userdata('user_id') . '
UNION DISTINCT
SELECT DISTINCT users.user_pic, users.id, users.username, contacts.accepted
FROM users
LEFT JOIN contacts ON users.id = contacts.user_2
WHERE user_1 = ' . $this->session->userdata('user_id')
);
Is there a way to see if the sessions 'user_id' was encountered in contacts.user_1 or contacts.user_2? Maybe by changing the query, or if i can use some if statements in the view?
Thanks in advance
George
yes you can add another field to select , that you can recognise like (1,2)
$this->db->query('
SELECT 1 as table_id,DISTINCT users.user_pic, users.id, users.username, contacts.accepted
FROM users
LEFT JOIN contacts ON users.id = contacts.user_1
WHERE contacts.user_2 = ' . $this->session->userdata('user_id') . '
UNION DISTINCT
SELECT 2 as table_id,DISTINCT users.user_pic, users.id, users.username, contacts.accepted
FROM users
LEFT JOIN contacts ON users.id = contacts.user_2
WHERE user_1 = ' . $this->session->userdata('user_id')
);
I typically use:
$id = $this->session->userdata('user_id');
then use $id in the query. Reads cleaner and on MySQL at least, if the query fails, it lists the value of $id. Never tried calling the session in the query before.
Related
I have following sql JOIN query:
public function exportAll($date) {
$sql = "SELECT CONCAT(u.firstname, u.lastname) as fullname, c.early_checkout_remarks, c.delayed_checkin_remarks, DATE(c.checkin_time) as checkin_date, DATE(c.checkout_time) as checkout_date, TIME(c.checkin_time) as checkin_time, TIME(c.checkout_time) as checkout_time
FROM users u
LEFT JOIN checkin_checkout c
ON u.id=c.users_id
AND (DATE(c.checkin_time) = '%s' OR DATE(c.checkout_time) = '%s')
AND u.deleted IS NULL
ORDER BY fullname,checkin_date";
$records = $this->db->exec(sprintf($sql,$date,$date));
return $records;
I only want records of users who are not deleted. But this query is also returning users with values in 'deleted' column.
For that I think you need to move
AND u.deleted IS NULL
into a WHERE clause. Currently that AND is applied to the join only, not to the final result. And since it's a LEFT join, it doesn't fully restrict the results.
Try:
SELECT
CONCAT(u.firstname, u.lastname) as fullname,
c.early_checkout_remarks,
c.delayed_checkin_remarks,
DATE(c.checkin_time) as checkin_date,
DATE(c.checkout_time) as checkout_date,
TIME(c.checkin_time) as checkin_time,
TIME(c.checkout_time) as checkout_time
FROM
users u
LEFT JOIN
checkin_checkout c
ON u.id = c.users_id
AND (DATE(c.checkin_time) = '%s' OR DATE(c.checkout_time) = '%s')
WHERE
u.deleted IS NULL
ORDER BY
fullname,
checkin_date
It's not clear from your question where the part about check-in dates should also be in the where clause. We'd need to know more about the requirements and your data structure. But it's something you can try if you need to.
Note also I reformatted your query - I (personally) find queries formatted like this can be read and understood a lot faster and more accurately. It's easier to see what is being done where, and what applies to what.
$sql = "SELECT CONCAT(u.firstname, u.lastname) as fullname, c.early_checkout_remarks, c.delayed_checkin_remarks, DATE(c.checkin_time) as checkin_date, DATE(c.checkout_time) as checkout_date, TIME(c.checkin_time) as checkin_time, TIME(c.checkout_time) as checkout_time
FROM users u
LEFT JOIN checkin_checkout c ON u.id=c.users_id
WHERE (DATE(c.checkin_time) = '%s' OR DATE(c.checkout_time) = '%s')
AND u.deleted IS NULL
ORDER BY fullname,checkin_date";
$records = $this->db->exec(sprintf($sql,$date,$date));
return $records;
WHERE added after the JOIN. You can use with ON as well.
Try below query.
SELECT CONCAT(u.firstname, u.lastname) as fullname, c.early_checkout_remarks, c.delayed_checkin_remarks, DATE(c.checkin_time) as checkin_date, DATE(c.checkout_time) as checkout_date, TIME(c.checkin_time) as checkin_time, TIME(c.checkout_time) as checkout_time
FROM users u
LEFT JOIN checkin_checkout c
ON u.id=c.users_id
Where (DATE(c.checkin_time) = '%s' OR DATE(c.checkout_time) = '%s')
AND u.deleted IS NULL
ORDER BY fullname,checkin_date
I have a query which I used PostgreSQL CTE(Common Table Expressions) feature :
WITH tmp_users AS (
SELECT users.id, users.name, users.email, users.created_at,sum(transactions.amount) as credit
FROM users INNER JOIN transactions
ON users.id = transactions.user_id
GROUP BY users.id,users.name,users.email, users.created_at, transactions.user_id
)
SELECT * FROM tmp_users WHERE credit > 100;
I can achieve the results with this :
$result = DB::select("WITH tmp_users AS (
SELECT users.id, users.name, users.email, users.created_at,sum(transactions.amount) as credit
FROM users INNER JOIN transactions
ON users.id = transactions.user_id
GROUP BY users.id,users.name,users.email, users.created_at, transactions.user_id
) SELECT * FROM tmp_users WHERE credit > 100");
But I need the Query Builder not only the results.
Any help would be greatly appreciated.
P.S:
Why I used postgres CTE feature?
Because in PostgreSQL if I want to do any statements on alias fields, I need to use CTE feature(Read more).
SELECT * FROM
(
SELECT u.id, u.name, u.email, u.created_at
,sum(t.amount) as credit
FROM users u
INNER JOIN transactions t ON u.id = t.user_id
GROUP BY u.id, u.name, u.email , u.created_at -- , t.user_id
) tmp_users
WHERE credit > 100;
Thank to #wildplasser
$query = DB::table('users')
->select('*')
->from(DB::raw(
'(SELECT u.id, u.name, u.created_at, sum(transactions.amount) as credit
FROM users as u INNER JOIN transactions as t ON u.id = t.user_id
GROUP BY u.id,u.name,u.created_at,t.user_id) as tmp_users'
));
I have PHP website with a table that prints out search results from a MySQL database via form with an input box. I use this SQL syntax and it works fine. I can search in one filed to get results from location.room_name and users.user_name:
SELECT:
SELECT computers.*, location.room_name AS location
FROM computers
LEFT JOIN location ON computers.location = location.id
LEFT JOIN users ON computers.user_1 = users.id".
" ".$searchCriterias."
ORDER BY id
WHERE:
$searchCriterias =
"WHERE
location.room_name LIKE '%".$s."%' OR
users.user_name LIKE '%".$s."%'
";
$s is the string from the search form.
The thing is that I have computers.user_1, computers.user_2 and computers.user_3 that all corresponds to users.id as in the syntax above. When I search for a username I would like to match it with user_1, user_2 and user_3 but I don't get it to work. I can only match it with one (in this case user_1).
I have tried to add LEFT JOIN users ON computers.user_2 = users.id and gets this error message: Not unique table/alias: 'users'
and...
LEFT JOIN users AS u1 ON computers.user_1 = users.id for all three and gets this messge: Unknown column 'users.id' in 'on clause'.
Why doesn't it work?
As you said you have 3 columns in computers table then try following while join. Also added GROUP BY to get unique result per user.
$query = "SELECT computers.*, location.room_name AS location
FROM computers
LEFT JOIN location ON computers.location = location.id
LEFT JOIN users ON (computers.user_1 = users.id
OR computers.user_2 = users.id
OR computers.user_3 = users.id ) ".
$searchCriterias . " GROUP BY users.id ORDER BY id";
Change your ON condition to IN statement :
SELECT computers.*, location.room_name AS location
FROM computers
LEFT JOIN location ON computers.location = location.id
LEFT JOIN users
ON ((users.id = computers.user_1) or
(users.id =computer.user_2 and not exists(select 1 from users t where t.id = computers.user_1)) OR
(users.id = computer.user_3 AND not exists(select 1 from users p where p.id IN(computer.user_2,computer.user_1))))".
" ".$searchCriterias."
ORDER BY id
Another option is to join against users 3 times, and amend your WHERE clause to check against 3 different tables.
Might need a DISTINCT to remove duplicates as I presume names can match multiple times.
This has the advantage over using an OR in the ON clause that it can still use indexes for the joins.
SELECT computers.*, location.room_name AS location
FROM computers
LEFT JOIN location ON computers.location = location.id
LEFT JOIN users users1 ON computers.user_1 = users1.id
LEFT JOIN users users2 ON computers.user_2 = users2.id
LEFT JOIN users users3 ON computers.user_3 = users3.id".
" ".$searchCriterias."
ORDER BY id
And the WHERE clause
$searchCriterias =
"WHERE
location.room_name LIKE '%".$s."%' OR
users1.user_name LIKE '%".$s."%' OR
users2.user_name LIKE '%".$s."%' OR
users3.user_name LIKE '%".$s."%'
";
I have the following tables and would like to query one more element from them.
categories table ->idcat(int), cat(varchar);
topics table ->idtopic(int), topic(varchar), idcat(int-fk), iduser(int-fk);
replies table ->idreply(int), reply(varchar) iduser(int-fk), idtopic(int-fk)
users table ->iduser(int), username(varchar).
My current query is;
$query = "SELECT t.topic, t.idtopic, u.username
FROM topics t
LEFT JOIN categories c ON t.idcat = c.idcat
LEFT JOIN users u ON t.iduser = u.iduser
WHERE c.idcat = '" . $idcat . "'";
Which presents 'Topic' and 'Username'. I'd like to show 'idReply' as well but don't know the proper JOIN syntax.
SELECT
t.topic,
t.idtopic,
u.username
FROM
topics t
LEFT JOIN
categories c ON t.idcat = c.idcat
LEFT JOIN
users u ON t.iduser = u.iduser
LEFT JOIN // new
replies r ON r.iduser = u.iduser AND r.idtopic = t.idtopic // new
WHERE c.idcat = '" . $idcat . "'";
This will generate a row for every reply to every topic in the specified category. Which could be a lot of records.
You may also want to experiment with the exact type of join on the replies table to get the result you want. LEFT JOIN is probably correct as you'll still get a result if there's no reply to a given topic. This may depend on your flavour of SQL.
OUTER JOIN & LEFT OUTER JOIN are possibilities.
Using INNER JOIN will ensure only topics with replies are returned.
You must have reply_id (foreign key) in your topics table. After that you can use this query.
$query = "SELECT t.topic, t.idtopic, u.username, r.id as reply_id
FROM topics t
LEFT JOIN categories c ON t.idcat = c.idcat
LEFT JOIN users u ON t.iduser = u.iduser
LEFT JOIN replies r ON t.reply_id = r.id
WHERE c.idcat = '" . $idcat . "'";
I get the following Error below from my query, and was wondering how can I fix this problem?
Duplicate column name 'user_id'
Here is My MySQL query.
"SELECT COUNT(users_friends.user_id) FROM ((SELECT *
FROM users_friends
INNER JOIN users ON users_friends.user_id = users.user_id
WHERE users_friends.user_id = '" . $user_id . "'
AND users_friends.friendship_status = '1')
UNION
(SELECT *
FROM users_friends
INNER JOIN users ON users_friends.friend_id = users.user_id
WHERE users_friends.friend_id = '" . $user_id . "'
AND users_friends.friendship_status = '1')) as friends"
Here is my new query.
SELECT COUNT(user_id) FROM ((SELECT users_friends.user_id
FROM users_friends
INNER JOIN users ON users_friends.user_id = users.user_id
WHERE users_friends.user_id = '" . $user_id . "'
AND users_friends.friendship_status = '1')
UNION
(SELECT users_friends.user_id
FROM users_friends
INNER JOIN users ON users_friends.friend_id = users.user_id
WHERE users_friends.friend_id = '" . $user_id . "'
AND users_friends.friendship_status = '1')) as friends
There's a couple of problems here. You obviously (read humor) only want a row count, so no need to SELECT *, true? I'm assuming you want to use a UNION to add rows together... Thus:
SELECT COUNT(*) AS the_count
FROM
(SELECT user_id AS ID
FROM users_friends
INNER JOIN users ON users_friends.user_id = users.user_id
WHERE users_friends.user_id = '" . $user_id . "'
AND users_friends.friendship_status = '1'
UNION
SELECT friend_id AS ID
FROM users_friends
INNER JOIN users ON users_friends.friend_id = users.user_id
WHERE users_friends.friend_id = '" . $user_id . "'
AND users_friends.friendship_status = '1'
) AS uf1;
Note: I'm assuming that the rest of the query (inner join, where, etc) works.
Edited, fixing the syntax problem with the ambiguous field names for ya.
SELECT COUNT(*) AS the_count
FROM
(SELECT uf.user_id AS ID
FROM users_friends uf
INNER JOIN users u ON uf.user_id = u.user_id
WHERE uf.user_id = '" . $user_id . "'
AND uf.friendship_status = '1'
UNION
SELECT uf.friend_id AS ID
FROM users_friends uf
INNER JOIN users u ON uf.friend_id = u.user_id
WHERE uf.friend_id = '" . $user_id . "'
AND uf.friendship_status = '1'
) AS uf1;
You are using SELECT * from , bringing all columns from 2 tables user_friends and users, both of them have a column called user_id. When you use a UNION it is my understanding that a temporary table is created, so MySQL is complaining that you have 2 columns with the same name. Try to explictly define the user_id you want to use for instance SELECT users.user_id, user_friends.abc etc
Edit:
If i understand this correctly, you are trying to get user ids of the friends.To me it seems like your previous query would return the $user_id in all records.
Try this:
SELECT COUNT(*) as CNT FROM
(
(SELECT users.user_id as uid
FROM users_friends
JOIN users ON users_friends.user_id = users.user_id
WHERE users_friends.friend_id = '" . $user_id . "'
AND users_friends.friendship_status = '1')
UNION
(SELECT users.user_id as uid
FROM users_friends
JOIN users ON users_friends.friend_id = users.user_id
WHERE users_friends.user_id = '" . $user_id . "'
AND users_friends.friendship_status = '1')
) as myfriends