sql join from 3 tables - php

I have 3 tables
user,
wink,
messages
Im going to clarify what i want because no one seems to understand
SELECT wink.*,user.id,user.points,user.gender,user.firstname,user.email
FROM wink
INNER JOIN user ON
(wink.id_user_from_wink=user.id OR wink.id_user_to_wink=user.id)
WHERE user.id!=?
AND (wink.id_user_from_wink=? OR wink.id_user_to_wink=?)
AND wink.wink_confirmed='1'
This works exactly as i want i to. I get the desired resultset, however now i need to get the last row matching from messages table.
I have tried using LEFT JOIN but it returns to many rows.
I need to return the last matching row for each result i get from the query above
As i said, i have tried:
SELECT wink.*,user.id,user.points,user.gender,user.firstname,user.email
FROM wink
INNER JOIN user ON
(wink.id_user_from_wink=user.id OR wink.id_user_to_wink=user.id)
LEFT JOIN messages ON (messages.id_user_from_message=user.id OR messages.id_user_to_message=user.id)
WHERE user.id!=?
AND (wink.id_user_from_wink=? OR wink.id_user_to_wink=?)
AND wink.wink_confirmed='1'
results:
[2] => Array
(
[id_wink_table] => 18
[id_user_from_wink] => 8
[id_user_to_wink] => 6
[wink_confirmed] => 1
[wink_date] => 2016-07-07 07:19:09
[id] => 8
[points] => 4
[gender] => 0
[firstname] =>
[email] => testuser1#hotmail.com
[id_messages_table] => 5
[id_user_from_message] => 6
[id_user_to_message] => 8
[message_text] => hejsan ss
[message_confirmed] => 0
[message_date] => 2016-07-09 02:43:59
)
[3] => Array
(
[id_wink_table] => 18
[id_user_from_wink] => 8
[id_user_to_wink] => 6
[wink_confirmed] => 1
[wink_date] => 2016-07-07 07:19:09
[id] => 8
[points] => 4
[gender] => 0
[firstname] =>
[email] => testuser1#hotmail.com
[id_messages_table] => 4
[id_user_from_message] => 6
[id_user_to_message] => 8
[message_text] => halluy
[message_confirmed] => 0
[message_date] => 2016-07-09 02:38:13
)
You can see that id_user_to_message and id_user_from_message are dublicate the only thing that differs is the message_text. So i want only the latest matching record from the messages table
EDIT:
SELECT wink.*,user.id,user.points,user.gender,user.firstname,user.email
FROM wink
INNER JOIN user
ON (wink.id_user_from_wink=user.id OR wink.id_user_to_wink=user.id)
**LEFT JOIN HERE returning latest message from messages table and join all rows that is returned when this left join is not used**
WHERE
user.id!=?
AND
(wink.id_user_from_wink=? OR wink.id_user_to_wink=?)
AND
wink.wink_confirmed='1'

/*
create table wink (id_wink_table int, id_user_from_wink int, id_user_to_wink int,wink_confirmed int,wink_date datetime);
insert into wink values
(18, 8,6,1,'2016-07-07 07:19:09'),(18,8,6,1,'2016-07-07 07:19:09');
create table user (id int,points int,gender int,firstaname varchar(20), email varchar(40));
truncate table user;
insert into user values
(8,4,0,null,'testuser1hotmail.com'), (8,4,0,null,'testuser1hotmail.com');
create table messages (id_messages_table int,id_user_from_message int,id_user_to_message int,message_text varchar(20),message_confirmed int,message_date datetime);
truncate table messages;
insert into messages values (5,6,8,'hejsan ss',0,'2016-07-09 02:43:59')
,(4,6,8,'halluy',0,'2016-07-09 02:38:13');
*/
select * from wink;
select * from user;
select * from messages;
SELECT wink.*,user.id,user.points,user.gender,user.firstaname,user.email, m.*
FROM wink
left outer JOIN user ON wink.id_user_from_wink = user.id OR wink.id_user_to_wink = user.id
left outer join messages m on m.id_user_from_message=user.id OR m.id_user_to_message=user.id
where m.id_messages_table =
(select max(m1.id_messages_table) from messages m1 where m.id_user_from_message=m1.id_user_from_message OR m.id_user_to_message = m1.id_user_to_message)

Related

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.

Issue with mysql joins

I have two tables
Meetings:
m_id ProjectName
1 Test
2 Test2
Meeting_next:
id fk_m_id Meetingdate status
1 1 9-1-2018 0
1 1 10-1-2018 0
1 1 13-1-2018 1
I want to join this two tables when I left join it I will get duplicate value
Expected output
Array
(
[0] => Array
(
[m_id] => 1
[ProjectName] => test
[meetingDate] =>13-1-2018
)
[1] => Array
(
[m_id] => 2
[ProjectName] => test2
[meetingDate] =>
)
)
I tried -
select * from meetings left join meeting_next on meetings.m_id= meeting_next.fk_m_id where meeting_next.status=1 order by m_id desc
myOutput:
Array
(
[0] => Array
(
[m_id] => 1
[ProjectName] => test
[meetingDate] =>13-1-2018
) )
Bad luck I got only first Project name. I need second too. Please help me. Any help would be appreciated.
Your WHERE condition filters the number of rows to only the row of the first project.
If you want to show both projects, even if there are no meetings with status 1, you need to move the condition to the join condition:
select *
from meetings
left join meeting_next
on meetings.m_id= meeting_next.fk_m_id
and meeting_next.status=1
order by m_id desc
Now you will get all rows from meetings with only the matching entries from meeting_next.

Order by not working with group by clause

I am using corequery of mysql in cakephp. I want the records in descending order. This is my table structure
enter code here
$coreQueryUser = $this->Message->query(
"select * from messages where messages.list_id = 3
group By (if(sender_id > reciever_id, sender_id, reciever_id)),
(if(sender_id > reciever_id, reciever_id, sender_id))
order by id desc
"
);
I want last message that belongs to (sender_id and reciver_id and viceversa) that belongs to list id 3
when i run this query i get the following output
<pre>Array
(
[0] => Array
(
[messages] => Array
(
[id] => 1
[sender_id] => 21
[reciever_id] => 10
[list_id] => 3
[message] => hello
[add_date] => 2016-09-25 00:00:00
[is_check] => 0
)
)
[1] => Array
(
[messages] => Array
(
[id] => 3
[sender_id] => 22
[reciever_id] => 10
[list_id] => 3
[message] => hello s
[add_date] => 2016-09-25 16:39:41
[is_check] => 0
)
)
)
but i wnat result like that:
Array
(
[0] => Array
(
[messages] => Array
(
[id] => 2
[sender_id] => 10
[reciever_id] => 21
[list_id] => 3
[message] => hello sir
[add_date] => 2016-09-25 00:00:00
[is_check] => 0
)
)
[1] => Array
(
[messages] => Array
(
[id] => 6
[sender_id] => 22
[reciever_id] => 10
[list_id] => 3
[message] => new
[add_date] => 2016-09-25 16:39:41
[is_check] => 0
)
)
)
Can anyone help me :(
The problem is that your query is against the sql standard because you have several fields in the select list that are neither in the group by list, nor are subject of an aggregate function, such as sum(). MySQL unfortunately allows such invalid queries to run under certain sql mode settings (the default settings of the most recent versions of MySQL would prevent such queries from running).
As MySQL documentation on group by clause says (bolding is mine):
If ONLY_FULL_GROUP_BY is disabled, a MySQL extension to the standard
SQL use of GROUP BY permits the select list, HAVING condition, or
ORDER BY list to refer to nonaggregated columns even if the columns
are not functionally dependent on GROUP BY columns. This causes MySQL
to accept the preceding query. In this case, the server is free to
choose any value from each group, so unless they are the same, the
values chosen are indeterminate, which is probably not what you want.
Furthermore, the selection of values from each group cannot be
influenced by adding an ORDER BY clause. Result set sorting occurs
after values have been chosen, and ORDER BY does not affect which
value within each group the server chooses.
You apparently want the latest record (with max(id) for each group. The proper way is to have a subquery that returns the max(id) per group and in the outer query join back to your main table using the ids to get the value of the other fields:
select m.*
from
messages m
inner join (
select max(id) as maxid
from messages
where messages.list_id = 3
group By (if(sender_id > reciever_id, sender_id, reciever_id)),
(if(sender_id > reciever_id, reciever_id, sender_id))
) t1 on m.id=t1.maxid
This code working:
SELECT * FROM generate_invoice
WHERE id IN
(
SELECT max(id) as id
FROM generate_invoice
GROUP by pay_id
ORDER by id DESC
)
How to group by DESC order
Try
SELECT * FROM ( SELECT * FROM generate_invoice ORDER BY id DESC ) AS g GROUP BY g.pay_id
OR
Use this code
SELECT m1.*,m2.* FROM generate_invoice m1 LEFT JOIN generate_invoice m2 ON (m1.pay_id = m2.pay_id AND m1.id < m2.id ) order by m1.id desc

multiple tables left join returns same value

Is it possible to make a query that will return one time the value of the second table and set the otherones at NULL. Im stuck with this.
This is my query
return $this->db->get_results(
"
SELECT id, name, type, check_in_days, check_out_days, all_check_out_days, minimum_stay, maximum_stay, all_accom, GROUP_CONCAT( accom_id ) as accom, GROUP_CONCAT( seasons_id ) as seasons, conditional_type
FROM $this->booking_rules_table
LEFT JOIN $this->booking_rules_accom_table
ON $this->booking_rules_table.id = $this->booking_rules_accom_table.rule_id
LEFT JOIN $this->booking_rules_seasons_table
ON $this->booking_rules_table.id = $this->booking_rules_seasons_table.rule_id
GROUP BY id
"
, ARRAY_A );
This returns a array like this
[2] => Array
(
[id] => 54
[name] =>
[type] => minimum_stay
[check_in_days] => 0,1,2,3,4,5,6
[check_out_days] => 0,1,2,3,4,5,6
[all_check_out_days] => 1
[minimum_stay] => 0
[maximum_stay] => 9999
[all_accom] => 0
[accom] => 7,7,7
[seasons] => 1,3,4
[conditional_type] => compulsory
)
You see that [accom] is returning the 7 3 times because the [seasons] has 3 values.
can i fix this with my query or is there an other solution. I dont want to explode it and build the array again.

Using LEFT OUTER JOIN to build query results

There are three tables like this:
store_stock:
ID ItemWeaveType ItemModel Cost Price
7 3 4 10.00 15.00
store_item_weaves:
ID WeaveID
3 MC
store_item_models:
ID ModelID
4 HV
I am trying to do a query to gather all of the data for item with the stock ID of 7. As a finished result, I would like an array like:
Array ( [ID] => 7 [ItemWeaveType] => MC [ItemModel] => HV [Cost] => 10.00 [Price] => 15.00)
So, I need to join the data from the tables store_item_weaves and store_item_models.
Here is what I have so far:
$query = $db->query("SELECT * FROM `store_stock` s
left outer join `store_item_weaves` w on w.`ID`=s.`ItemWeaveType`
left outer join `store_item_models` m on m.`ID`=s.`ItemModel`
where s.`ID`=7");
This returns an array like:
Array ( [ID] => 7 [ItemWeaveType] => 3 [ItemModel] => 4 [Cost] => 10.00 [Price] => 15.00 [WeaveID] => MC [ModelID] => HV )
So, I'm almost there. Instead of using the values of WeaveID and ModelID for ItemWeaveType and ItemModel, it is adding it onto the array.
Any ideas?
Use a columns list instead of just * to make sure you get the values you want:
$query = $db->query("SELECT s.ID, w.WeaveId, m.ModelId, s.Cost, s.Price FROM `store_stock` s
left outer join `store_item_weaves` w on w.`ID`=s.`ItemWeaveType`
left outer join `store_item_models` m on m.`ID`=s.`ItemModel`
where s.`ID`=7");

Categories