Return one result per ChatID - php

I am getting data from a table and ordering them by a column in another table. Below is my query.
$query = "SELECT Chatroom.ChatID, Chatroom.User1, Chatroom.User2 FROM `Chatroom` JOIN `Messages` ON Chatroom.ChatID = Messages.ChatID WHERE User1 = ? OR User2 = ? ORDER BY Messages.MessageDate";
Say there is a chat between two people and they've messaged 10 times. I will get 10 results when really I want 1 result. I realize it's looping through messages because I joined them on chatID but I do that to get the dates.
Is there a better way to get this or is there any easy adjustment to my query that will work?

If you're using MySQL, maybe try this?
SELECT c.ChatID, c.User1, c.User2
FROM Chatroom AS c
JOIN (
SELECT mx.*
FROM Messages AS mx
WHERE mx.ChatID = c.ChatID
ORDER BY mx.MessageDate
LIMIT 1
) AS m ON m.ChatID = c.ChatID
WHERE c.User1 = ?
OR c.User2 = ?
ORDER BY m.MessageDate;
Try this instead?
SELECT c.ChatID, c.User1, c.User2
FROM Messages AS m
JOIN Chatroom AS c on c.ChatID = m.ChatID
WHERE (c.User1 = ? OR c.User2 = ?)
GROUP BY c.ChatID
ORDER BY m.MessageDate

Related

Mysql Retrieve Specific Number of grouped rows from a join

So I created this query
SELECT a.email
, a.password
, a.server
, a.status
, a.step
, b.*
FROM mail a
JOIN automation_logs b
ON b.accountid = a.accountid
WHERE a.status <0
ORDER
BY b.created DESC;
What it's used for is essentially I'm trying to get debug information from our log table for email accounts that are errored out on our api. The automation_logs table essentially is text dump of error messages that were produced by our API.
This query gives me what I want but gives me too much. I only want the last five most recent (read: created field is a timestamp) error messages for any of the accounts as some of these accounts have existed for years and old errors have been fixed and aren't necessary to know what's broken and just pad the results.
Is this possible with a single query?
Following the advice listed here: Thank you Marshal Tigerus
I was able to get it to work with the following sql:
SET #currcount = NULL, #currvalue = NULL;
SELECT a.email,a.password,a.serverid,a.status,a.step,b.message,b.created FROM mail as a JOIN (
SELECT * FROM (
SELECT
*,
#currcount := IF(#currvalue = accountid, #currcount + 1, 1) AS num,
#currvalue := accountid AS cur_id
FROM automation_logs
WHERE message NOT LIKE ""
ORDER BY accountid, created DESC
) as limitedresults WHERE num <= 5
) as b ON a.accountid = b.accountid WHERE a.status < 0 ORDER BY b.created DESC

Complicated INNER JOIN Mysql Query From 3 Tables in Laravel

I've been on this for a few hours without solution. I thought of laravel relationships but don't know how to pass a second condition because I need to relate with 3 tables. I'd like to use the query below in laravel.
SELECT
subscriptions.subscribed_to,
broadcasts. *,
FROM subscriptions
INNER JOIN broadcasts
WHERE subscriptions.subscriber = {$user_id}
AND (
SELECT COUNT(*) FROM seen_broadcasts
WHERE user_id = {$user_id}
AND broadcast_id = broadcasts.id
) = 0
ORDER BY broadcast.date DESC
There are 3 tables.
subscriptions: subscriber_id subscribes to broadcaster_id.
broadcasts: where broadcaster's message is saved.
seen_broadcast: where the information of subscribers are saved when they read a broadcast. This helps us provide detailed stats to broadcaster. user_id = subscriber_user_id, broadcast_id = broadcast_message_id
I want to be able to get broadcasts from all broadcaster that userA has subscribed to and have not seen.
The query above currently works outside laravel.
After much runarounds, I ended up with this:
$broadcast_result = DB::select( DB::raw("
SELECT
subscriptions.subscribed_to,
broadcasts.*
FROM subscriptions
INNER JOIN broadcasts
WHERE subscriptions.browser_agent_id = :subsc_id
AND broadcasts.user_id = subscriptions.subscribed_to
AND (
SELECT COUNT(*) FROM broadcasts_seen
WHERE broadcast_id = broadcasts.id
AND subscriber_id = subscriptions.subscriber_id
) = 0
ORDER BY broadcasts.date DESC LIMIT 1
"), array(
'subsc_id' => $subscriber->id
));
$broadcast_set = $broadcast_result[0];
Also add use DB; in the controller.
If there's a better way to do this, please share.

How to make MySQL select a random winner when using INNER JOIN

SELECT * FROM `surveys` INNER JOIN `surveyusers` ON `surveyusers`.`survID` = `surveys`.`survID` WHERE `surveyusers`.`hasWon` = 0 ORDER BY RAND();
UPDATE surveys SET winner = email;
This was a school assignment that required us to select and update the survey winner.
I use PHP to manage and show surveys, I want the SQL to pick the winner. PHP sets survID
I want to pick a random winner and set the winner coloumn in surveys table to the email in the surveyusers table. But I really have a lot of trouble with it.
Updates can take the same syntax as a Select.
You can combine these two queries into one.
UPDATE `surveys` `s` SET `s`.`winner` = (
SELECT email FROM `surveyusers`
WHERE `surveyusers`.`hasWon` = 0
AND `survID` = 1
ORDER BY RAND()
LIMIT 1
) WHERE `survID` = 1;
The survID you would have to set from PHP of course.
You can nest a SELECT query within your UPDATE query:
UPDATE surveys SET winner = (
SELECT `surveyusers`.email FROM `surveys`
INNER JOIN `surveyusers` ON `surveyusers`.`survID` = `surveys`.`survID`
WHERE `surveyusers`.`hasWon` = 0 ORDER BY RAND() LIMIT 1
) WHERE `survID` = xxx
where xxx is the survey to update.

Query with join query, need assistance

I have three tables.
I combine the company and component tables with this code
$questions_query = "SELECT company_mast.id, component_mast.component_id
FROM company_mast
LEFT JOIN component_mast
ON company_mast.id = component_mast.company_id
WHERE component_mast.component_name = '".$component_name."'
AND company_mast.company_name = '".$company_name."'";
The result is as desired, If I put company_name as Bells and component_name as Assets I get and id of 3 for Bells and an id of 9 for Assets. Now if you look at the customfields table I need to pull all the questions with the a specific company_id and component_id.
Example: If the user enters Bells and Assets they need to receive all questions with the company_id of 3 and the component_id of 9.
So this is my query
SELECT *
FROM customfield_mast
LEFT JOIN ( SELECT company_mast.id, component_mast.component_id
FROM company_mast
LEFT JOIN component_mast
ON company_mast.id = component_mast.company_id
WHERE component_mast.component_name = 'Assets'
AND company_mast.company_name = 'Bells')
att
ON customfield_mast.company_id = customfield_mast.component_id
This however returns all questions in my db, which is not what I want. I'm positive my last "ON" statement is the problem, however I don't know what the correct statement would be. I have not started with SQL injection protection, this is grass roots to get my queries to work. Thanks for the help
What's wrong with another join?
SELECT company_mast.id, component_mast.component_id, CFM.DisplayName
FROM company_mast
LEFT JOIN component_mast
ON company_mast.id = component_mast.company_id
LEFT JOIN CustomField_mast CFM
ON CFM.Company_ID = Component_mast.Company_ID
and CFM.Component_ID = component_Mast.Component_ID
WHERE component_mast.component_name = '".$component_name."'
AND company_mast.company_name = '".$company_name."'";
SELECT * FROM `customfield_mast`
WHERE `company_id` =
(SELECT `id` FROM `company_mast` WHERE `company_name` = '$company_name')
AND `component_id` IN
(SELECT GROUP_CONCAT(`component_id`) FROM `component_mast`
WHERE `component_name` = '$component_name')

MySQL returning value only for ID 1

I got the following query:
SELECT ur.repair_id, ur.repair_complete, ur.repair_noted_by_client, ur.repair_problem, ur.added_at, ur.added_by, ur.repaired_at, ur.repaired_by,
aa.account_fullname AS added_by_name,
ar.account_fullname AS repaired_by_name
FROM units_repairs AS ur
LEFT JOIN (SELECT account_id, account_fullname FROM accounts LIMIT 1) AS aa ON aa.account_id = ur.added_by
LEFT JOIN (SELECT account_id, account_fullname FROM accounts LIMIT 1) AS ar ON ar.account_id = ur.repaired_by
WHERE ur.unit_id = 1
It return the fullname only if the account_id = 1. If let say repaired_by = 2 then it say NULL...
Thanks, I don't know what I am missing.
You are joining with inner query:
SELECT account_id, account_fullname FROM accounts LIMIT 1
where you have LIMIT 1, which gives you only one row (which probably has repaired_by = 1), and then you want to filter and get only rows where repaired_by is 2...and you don't have that one.
Probably there are no records that satisfy the condition repaired_by = 2 in the line,
LEFT JOIN (SELECT account_id, account_fullname FROM accounts LIMIT 1) AS ar ON ar.account_id = ur.repaired_by
Hence, ar.account_id = ur.repaired_by returns NULL.

Categories