how to get two rows from a table using join - php

this is my code
$query = $this->db
->select('*')
->join('users as receiver', 'receiver.user_id = messages.user1')
->join('users as sender', 'sender.user_id = messages.user2')
->get('messages')->result_array();
this is database
users table
user_id |username | datetime
1 | abc1 | 000000000
2 | abc2 | 000000000
messages table
msg_id | user1 | user2 | msg | timestamp
1 | 1 | 2 | hello | 000000000
i want to get records of two users as sender and receiver. but this join give me record of last join. in this case i m getting record of sender.
i want output like this
[0] => Array
(
[user1] => stdClass Object
(
[id] => 1
[username] => abc1
[datetime] => 2016-11-07 03:00:00
)
[user2] => stdClass Object
(
[id] => 2
[username] => abc2
[datetime] => 2016-11-07 00:00:00
)
[message] => stdClass Object
(
[id] => 1
[message] => hdf
[timestamp] => 2016-11-06 08:43:26
)
)
thanks in advance

Here is the SQL to create a union query that will give you two rows
select * from messages m join users u on u.user_id = m.user1 union all select * from messages m join users u on u.user_id = m.user2;
or with a join statement for two users in one row
select * from messages m join users u1 on u1.user_id = m.user1 join users u2 on u2.user_id = m.user2;

Related

Consolidate Query Results into Single Index

I have a table (usermeta - 2nd below) that is causing my trouble. I need to get 2 values from this table in 1 query and return the results in a single array index.
One table (users) contains the following:
ID | user_email | display_name |
-----+------------------+---------------|
8 | bob#bobjones.com | bob jones |
9 | rob#robsmith.com | rob smith |
Another table (usermeta) contains:
user_id | meta_key | meta_value |
----------+--------------+--------------|
8 | phone_number | 4441234433 |
8 | rep_id | abc123 |
9 | phone_number | 5552323322 |
9 | rep_id | xyz456 |
My SQL query:
function get_this() {
global $db;
$get = $db->get_results("
SELECT
um.meta_key, um.meta_value, um.user_id, user.user_email, user.display_name
FROM
users as user
LEFT OUTER JOIN
usermeta as um
ON
user.ID = um.user_id
WHERE
um.meta_key='rep_id'
OR
um.meta_key='phone_number'
");
return $get;
}
Calling the function: $foo = get_this(); returns this array:
Array
(
[0] => stdClass Object
(
[meta_key] => phone_number
[meta_value] => 4441234433
[user_id] => 8
[user_email] => bob#bobjones.com
[display_name] => bob jones
)
[1] => stdClass Object
(
[meta_key] => rep_id
[meta_value] => abc123
[user_id] => 8
[user_email] => bob#bobjones.com
[display_name] => bob jones
)
[2] => stdClass Object
(
[meta_key] => phone_number
[meta_value] => 5552323322
[user_id] => 9
[user_email] => rob#robsmith.com
[display_name] => rob smith
)
[3] => stdClass Object
(
[meta_key] => rep_id
[meta_value] => xyz456
[user_id] => 9
[user_email] => rob#robsmith.com
[display_name] => rob smith
)
)
The problem I am having is in consolidating the data based on user_id. I'd like to return an array that includes both their phone number AND their rep id along with their user_id, user_email and display_name in one index so I can print something like: bob jones, bob#bobjones.com, 4441234433, abc123
I clearly do not know what question to ask as I've spent 3 days now researching this site and the Internet and trying various combinations of CASE, AND, OR, WHERE, UNION, GROUP etc. to no avail. I am happy to manage this on the PHP end but have failed in that department as well.
You could put two different meta values on the same row of result by joining twice to the meta table:
SELECT user.user_id, user.user_email, user.display_name,
um1.meta_value AS `rep_id`,
um2.meta_value AS `phone_number`
FROM users AS user
LEFT OUTER JOIN usermeta AS um1
ON user.ID = um1.user_id AND um1.meta_key = 'rep_id'
LEFT OUTER JOIN usermeta AS um2
ON user.ID = um2.user_id AND um2.meta_key = 'phone_number'

php list and select data using join tables

I have this database table structure for posts, categories and post_categories
posts:
| id | title | details
| 1 | test | test details
categories:
| id | name | parent_id
| 1 | cat one | 0
| 2 | cat two | 0
| 3 | cat three | 0
post_categories
| category_id | post_id
| 1 | 1
| 2 | 1
I insert multiple categories using input checkbox for each post in post_categories table. Now in update page(domain.com/admin/posts/1/edit) i need to show categories list and checked input checkbox.can i generate this output using join two table(categories and post_categories) Or I need to separate two query(first from post_category table and second from categories table) like this output?! (my choice is join method so how to generate use join method?)
<input type="checkbox" value="1" checked> cat one
<input type="checkbox" value="2" checked> cat two
<input type="checkbox" value="3"> cat three //unchecked (not in post_categories table)
update:
for list categories query:
$query = $this->db->table('categories')
->select('id, name, parent_id')
->get()
->getResultObject();
data in print_r:
Array
(
[0] => stdClass Object
(
[id] => 1
[name] => cat one
[parent_id] => 0
)
[1] => stdClass Object
(
[id] => 2
[name] => cat two
[parent_id] => 0
)
[2] => stdClass Object
(
[id] => 3
[name] => cat three
[parent_id] => 0
)
[3] => stdClass Object
(
[id] => 4
[name] => cat4
[parent_id] => 2
)
[4] => stdClass Object
(
[id] => 5
[name] => cat5
[parent_id] => 0
)
[5] => stdClass Object
(
[id] => 6
[name] => cat6
[parent_id] => 0
)
)
after join:
$query = $this->db->table('categories')
->select('id, name, parent_id')
->join('post_categories', 'post_categories.category_id = id','left outer')
->where('post_categories.post_id', $id)
->get()
->getResultObject();
and data is:
Array
(
[0] => stdClass Object
(
[id] => 1
[name] => cat one
[parent_id] => 0
)
[1] => stdClass Object
(
[id] => 4
[name] => cat two
[parent_id] => 2
)
)
result after join is false.
You can do this with one query but for this, you need one extra column in query for checking category is using or not.
SELECT id, name, if(pc.cat_id IS NULL,0,1) as `value` from categories as ct LEFT JOIN post_categories as pc on pc.cat_id = ct.id
demo link
I hope this query will fulfill your requirements.
If you need more detail about this you can visit this StackOverflow thread
MySQL Join and create new column value
You can run below query to get the categories selected:
select post_categories.category_id from posts
left join post_categories on post_categories.post_id=posts.id
left join categories on post_categories.category_id=categories.id;
get these ids to an array and within your category loop check if the ids are in array and make them checked.
quite easy !

Merge result after query with JOIN clause in Mysql

I have two table like this:
Product
id | title
-------------------------------
1 | Skirt
2 | Pants
Product_thumbnail
id | product_id | image
-------------------------------
1 | 1 | pant.jpg
2 | 1 | shoes.png
When I want to get product with the thumbnail, I query like this:
SELECT p.*, pt.image FROM product p
LEFT JOIN product_thumbnail pt ON pt.product_id = p.id;
The output I expected
[0]=> [
[id] => 1
[image] =>
[
[0] => pant.jpg
[1] => shoes.jpg
]
]
[1]=> [
[id] => 2
[image] => null
]
But the real output
[0]=> [
id => 1
image => pant.jpg
]
[1]=> [
id => 1
image => shoes.jpg
]
[2]=> [
id => 2
image => shoes.jpg
]
As you see, there is 2 element duplicate, so I need to merge it by hand, is there any way to achieve this more easy? Because my table have many tables relate together more than this, I'm using PHP, I use array_merge_recursive() to merge them but if do like that I get duplicate value in each field, like this:
[0]=> [
[id] =>
[
[0] => 1
[1] => 1
]
[image] =>
[
[0] => pant.jpg
[1] => shoes.jpg
]
]
It's not what I want, can anyone give me an idea?
Consider the following. The code could I'm sure be written more economically, but hopefully you get the idea...
<?php
/*
DROP TABLE IF EXISTS product;
CREATE TABLE product
(id SERIAL PRIMARY KEY
,title VARCHAR(12) NOT NULL UNIQUE
);
INSERT INTO product VALUES
(1,'Hat'),
(2,'Shoe');
DROP TABLE IF EXISTS product_thumbnail;
CREATE TABLE product_thumbnail
(id SERIAL PRIMARY KEY
,product_id INT NOT NULL
,image VARCHAR(12) NOT NULL UNIQUE
);
INSERT INTO product_thumbnail VALUES
(1,1,'sombrero.jpg'),
(2,1,'stetson.png');
SELECT p.id
, p.title
, t.image
FROM product p
LEFT
JOIN product_thumbnail t
ON t.product_id = p.id;
+----+-------+--------------+
| id | title | image |
+----+-------+--------------+
| 1 | Hat | sombrero.jpg |
| 1 | Hat | stetson.png |
| 2 | Shoe | NULL |
+----+-------+--------------+
*/
require('path/to/connection/stateme.nts');
$query = "
SELECT p.id
, p.title
, t.image
FROM product p
LEFT
JOIN product_thumbnail t
ON t.product_id = p.id;
";
$result = mysqli_query($db,$query);
$old_array = array();
while($row = mysqli_fetch_assoc($result)){
$old_array[] = $row;
}
$new_array = array();
foreach ($old_array as $row) {
$new_array[$row['id']]['title'] = $row['title'];
$new_array[$row['id']]['image'][] = $row['image'];
}
$new_array = array_values($new_array); // reindex
print_r($new_array);
?>
Outputs
Array
(
[0] => Array
(
[title] => Hat
[image] => Array
(
[0] => sombrero.jpg
[1] => stetson.png
)
)
[1] => Array
(
[title] => Shoe
[image] => Array
(
[0] =>
)
)
)
MySQL doesn't support arrays, but you can aggregate the data into a string:
SELECT p.*, GROUP_CONCAT(pt.image) as images
FROM product p LEFT JOIN
product_thumbnail pt
ON pt.product_id = p.id
GROUP BY p.id;
Note that aggregating only by the id and selecting p.* is allowed and even standard SQL -- assuming that id is a primary key or declared to be unique. This is the one situation when this syntax is permitted.

select GROUP_CONCAT in mysql

I have two tables:
table1:
id email
1 john#gmail.com
2 doe#gmail.com
table2:
userid key value
1 firstname john
1 phone 112233
2 firstname doe
2 phone 223344
This is mysql query without condition:
SELECT a.*,
b.*,
GROUP_CONCAT(b.key),
GROUP_CONCAT(b.value)
FROM table1 a
LEFT JOIN table2 b ON a.id = b.userid
This is result:
array(
[id] => 1
[email] => john#gmail.com
[userid] => 1
[key] => firstname,phone
[value] => john,112233
)
array(
[id] => 2
[email] => doe#gmail.com
[userid] => 2
[key] => firstname,phone
[value] => doe,223344
)
This is mysql query with condition:
SELECT a.*,
b.*,
GROUP_CONCAT(b.key),
GROUP_CONCAT(b.value)
FROM table1 a
LEFT JOIN table2 b ON a.id = b.userid
WHERE b.key = "firstname"
AND b.value LIKE '%jo%'
And this is result:
array(
[id] => 1
[email] => john#gmail.com
[userid] => 1
[key] => firstname
[value] => john
)
But I want this:
array(
[id] => 1
[email] => john#gmail.com
[userid] => 1
[key] => firstname,phone
[value] => john,112233
)
There any way to do this? thank for any help!
Your queries are lacking the GROUP BY clause to get a row per user. Then use a HAVING clause to make sure the aggregated row includes a firstname '%jo%':
SELECT a.*,
GROUP_CONCAT(b.key),
GROUP_CONCAT(b.value)
FROM table1 a
LEFT JOIN table2 b ON a.id = b.userid
GROUP BY a.id
HAVING sum(b.key = 'firstname'
AND b.value LIKE '%jo%') > 0;
true results in 1, false in 0 in MySQL. So checking whether the sum is greater than zero means checking whether the condition is true at least once.

PHP SQL left join fetch all

I have 3 mysql tables from where I am trying to fetch data
Table: list
list_id | name | description
-------------------------------------
1234 | name1 | sample description1
1235 | name2 | sample description2
Table: list_to_category
id | list_id | category_id
--------------------------------
1 | 1234 | 1
2 | 1234 | 2
3 | 1234 | 3
4 | 1235 | 2
5 | 1235 | 3
And table: category
id | title | parent_id
--------------------------------
1 | Category 1 | 0
2 | Category 2 | 0
3 | Category 3 | 0
And from PHP SQL query I want to fetch data like below
1. name1 - category 1, category 2, category 3
2. name2 - category 2, category 3
I tried below query
SELECT list.name, category.title FROM list
LEFT JOIN list_to_category
ON list.id = list_to_category.list_id
LEFT JOIN category
ON list_to_category.id = category.id
This gives me only single category name assigned to a list like this
1. name1 - category 1
2. name2 - category 2
Is it possible in single query?
You can use GROUP_CONCAT for this:
select
l.list_id,
l.name,
group_concat(distinct c.title) categories
from list l
left join list_to_category lc
on l.list_id = lc.list_id
left join category c
on lc.category_id = c.id
group by l.list_id
You can try this solution.
select l.list_id, l.name, (select group_concat(c.title) from list_to_category ltc JOIN category c ON c.id=ltc.category_id where ltc.list_id=l.id) from list l
Hope this will help you!!!
Use GROUP_CONCAT for group by "name" to fetch result :
SELECT L.name, GROUP_CONCAT(C.title) as title FROM list L
LEFT outer JOIN list_to_category LC ON L.list_id = LC.list_id
LEFT outer JOIN category C ON LC.category_id = C.id
group by L.name
Use GROUP_CONCAT for group by "list_id" for same name of list to fetch result :
SELECT L.name, GROUP_CONCAT(C.title) as title FROM list L
LEFT outer JOIN list_to_category LC ON L.list_id = LC.list_id
LEFT outer JOIN category C ON LC.category_id = C.id
group by L.list_id
It should be apparent from the code below that I'm no PHP coder. However, this should get the idea across. You can also use javascript/css to handle the transformation, which means things can be even more dynamic...
Oh, and I changed some table/column names - because I like it better that way...
<?php
require('path/to/connection/statements'); // $con
$query = "
SELECT l.list_id
, l.name
, l.description
, c.category_id
, c.title
, c.parent_id
FROM list l
JOIN list_category lc
ON lc.list_id = l.list_id
JOIN category c
ON c.category_id = lc.category_id
ORDER
BY l.list_id
, c.category_id;
";
$result = mysqli_query($con,$query);
$my_array = array();
while($row = mysqli_fetch_assoc($result)){
$my_array[] = $row;
}
$new_array = array();
foreach ($my_array as $row)
{
$new_array[$row['list_id']][$row['name']][$row['description']][] = $row['title'];
}
print_r($new_array);
?>
This will turn an array like this:
Array
(
[0] => Array
(
[list_id] => 1234
[name] => name1
[description] => sample description1
[category_id] => 1
[title] => Category 1
[parent_id] => 0
)
[1] => Array
(
[list_id] => 1234
[name] => name1
[description] => sample description1
[category_id] => 2
[title] => Category 2
[parent_id] => 0
)
[2] => Array
(
[list_id] => 1234
[name] => name1
[description] => sample description1
[category_id] => 3
[title] => Category 3
[parent_id] => 0
)
[3] => Array
(
[list_id] => 1235
[name] => name2
[description] => sample description2
[category_id] => 2
[title] => Category 2
[parent_id] => 0
)
[4] => Array
(
[list_id] => 1235
[name] => name2
[description] => sample description2
[category_id] => 3
[title] => Category 3
[parent_id] => 0
)
)
...into an array like this...
Array
(
[1234] => Array
(
[name1] => Array
(
[sample description1] => Array
(
[0] => Category 1
[1] => Category 2
[2] => Category 3
)
)
)
[1235] => Array
(
[name2] => Array
(
[sample description2] => Array
(
[0] => Category 2
[1] => Category 3
)
)
)
)
try this code
select l.name,c.title
from list_to_category lc join list l on lc.list_id=l.id
join category c on lc.catg_id=c.id

Categories