MySql query to retrieve a conversation between 2 users - mysql

I'm having a quick issue I could use an opinion on. I'm attempting to write a MySQL query that pulls all the messages from a conversation that is exclusively between two users.
I need to be able to pull messages sent by 'user1' that are sent to 'user2', and messages sent by 'user2' that are sent to 'user1'.
I've dabbled a bit and I've currently got the 4 conditions needed for my query to execute (see below). I've been trying to work out what way to structure it to get the specific data I need though.
SELECT privatemessage_message, privatemessage_time_created, privatemessage_sent_by, privatemessage_sent_to
FROM tbl_privatemessages
WHERE privatemessage_sent_by = 1
OR privatemessage_sent_by = 2
OR privatemessage_sent_to = 1
OR privatemessage_sent_to = 2
ORDER BY privatemessage_time_created ASC
For context :
This is going to be used within a PHP MySQL website with AJAX being used for the private messaging. I'm fine withthem sides of it, but this particular SQL query is a nuisance.
Any help is greatly appreciated :)

You need to use AND to combine the sender and recipient, and OR to combine the different directions.
SELECT privatemessage_message, privatemessage_time_created, privatemessage_sent_by, privatemessage_sent_to
FROM tbl_privatemessages
WHERE (privatemessage_sent_by = 1 AND privatemessage_sent_to = 2)
OR (privatemessage_sent_to = 1 AND privatemessage_sent_by = 2)
ORDER BY privatemessage_time_created ASC

Related

How to update the balance with random value (mysql) when a user registers the website?

For one of my courses, I'm trying to create banking system website using mysqldb and to write the code that make it possible for me to update users balance with random value while registration so the balance will not depend on the user's registration inserted information. i want the value to be inserted to the right spot in the table, only if this spot is null.
i used the code below:
$cursor = $MySQLdb->prepare("UPDATE users SET Balance=(Select FLOOR(0+ RAND() * 10000)) WHERE Balance=null AND userID=<userID>;")
I hope I was understood.
Thanks in advance
First of all, I would never put a calculation in a query string ;)
Also don't overcomplicate the rand() function. Take a look on the docs: rand() function docs
And lastly maybe think about it that is it a good idea to leave it on null? Maybe you could do something like 1 or so. (Only if it not possible for someone to have 1 money!!)
Do something like:
$balance_variable = $balance_variable = rand(5000, 10000);
$userID_variable = /*specify it somehow*/;
$cursor = $MySQLdb->prepare("UPDATE users SET Balance=? WHERE Balance IS NULL AND userID=?");
$cursor->bind_param('ss', $balance_variable, $userID_variable);
$cursor->execute();

Get All Tickets in OSticket

Can someone help me figure out how I can retrieve all tickets? I read online and saw that there's no API to do this yet? I also read that i can write some sql code to retrieve them?
My objective is: Check OSticket to see if the ticket with the same subject is created more than 3 times, then to basically alert me ( for now it can just be a message in Powershell that says it, as I'm scripting in PS).
For that I need to retrieve all tickets in the OSticketDB. Since I just have it locally for now, I have a sql DB setup but I don't see something along the lines of ost_tickets? Not sure how I can retrieve tickets that have been duplicates from same subject.
I'm not sure I understand your question correctly. But here is SQL query, that will return all tickets, where subject has occurred more than 3 times.
SELECT
cdata.ticket_id,
cdata.subject,
ticket.number,
subjectstable.subjectcount
FROM
osticketdb.ost_ticket AS ticket
INNER JOIN osticketdb.ost_ticket__cdata AS cdata ON ticket.ticket_id = cdata.ticket_id
INNER JOIN
(SELECT subject, COUNT(*) as subjectcount FROM osticketdb.ost_ticket__cdata GROUP BY subject) AS subjectstable
ON subjectstable.subject = cdata.subject
WHERE subjectstable.subjectcount > 3

MYSQL Selecting specific rows or first row if doesn't exist

I have a table of texts from various dates. Each is indexed by service, variation, and page and sub-page ids.
I need to fetch all entries for a given service, page and sub-page. i.e. each variation! BUT If the particular specific subpage doesn't exist, I need it to fetch the first subpage for that page, rather than nothing for that variation.
This is my code -
SELECT * FROM frames f
LEFT JOIN varients v ON f.varient_id = v.varient_id AND f.service_id = v.service_id
ẀHERE f.service_id = :sid
AND f.frame_id = :fid
AND (f.subframe_id = :subid
OR f.subframe_id = (
select min(subframe_id) from frames ff
ẀHERE ff.service_id = f.service_id
AND ff.varient_id = f.varient_id AND ff.frame_id = f.frame_id
)
)
GROUP BY f.service_id, f.varient_id, f.frame_id
ORDER BY f.service_id, v.varient_date, f.frame_id, f.subframe_id
but as often as not this just gives the minimum rather than the specific, even when the specific value exists. I'm pretty sure that the OR isn't what I need..
I've tried working with UNION as per some other answers, but since I want more than a single result, I can't seem to work it out!
Thanks for any help ..
OK. I managed to achieve what I wanted. Two days of messing with this, and finally work it out after posting a question. I was helped by one of the 'related' questions, which whilst not giving me an answer, made me think about it a different way -
I basically turned the whole thing inside out: As i only wanted one result per variation, I used that as the primary table. Then Joined the 'frames' table twice, once for the specific value, and once for the first value (found using a search for MIN().) Used IFNULL to return the second record if the first wasn;t found. An extra IS NOT NULL check against the second record within the WHERE to avoid returning anything where there is nothing stored against the variation record.
SELECT v.service_id, v.varient_id, IFNULL(f.frame_id,ff.frame_id)as frame_id,
IFNULL(f.subframe_id,ff.subframe_id) as subframe_id , IFNULL(f.frameunique, ff.frameunique) as frameunique, IFNULL(f.frame_content,ff.frame_content) as framecontent
FROM varients v
LEFT JOIN `frames` f ON `f`.`varient_id` = `v`.`varient_id` AND `f`.`service_id` = `v`.`service_id` AND `f`.`frame_id` = 698 AND `f`.`subframe_id` = 0004
LEFT JOIN `frames` ff ON `ff`.`varient_id` = `v`.`varient_id` AND `ff`.`service_id` = `v`.`service_id` AND `ff`.`frame_id` = 698
AND `ff`.`subframe_id` = (select min(`subframe_id`) from `frames` `fff` where `fff`.`service_id` = `v`.`service_id`
AND `fff`.`varient_id` = `v`.`varient_id` AND `fff`.`frame_id` = 698 )
where `v`.`service_id` = 3 AND ff.frameunique IS NOT NULL
ORDER BY `f`.`service_id`, `v`.`varient_date`, `f`.`frame_id`, `f`.`subframe_id`
Posting this in case it helps anybody else. It still needs tidying but it works. Thanks for the comments. :)

MySQL finding data if any 4 of 5 columns are found in a row

I have an imported table of several thousand customers, the development I am working on runs on the basis of anonymity for purchase checkouts (customers do not need to log in to check out), but if enough of their details match the database record then do a soft match and email the (probably new) email address and eventually associate the anonymous checkout with the account record on file.
This is rolling out this way due to the age of the records, many people have the same postal address or names but not the same email address, likewise some people will have moved house and some people will have changed name (marriage etc).
What I think I am looking for is a MySQL CASE system, however the CASE questions on Stack Overflow I've found don't appear to cover what I'm trying to get from this query.
The query should work something like this:
$input[0] = postcode (zip code)
$input[1] = postal address
$input[2] = phone number
$input[3] = surname
$input[4] = forename
SELECT account_id FROM account WHERE <4 or more of the variables listed match the same row>
The only way I KNOW I can do this is with a massive bunch of OR statements but that's excessive and I'm sure there's a cleaner more concise method.
I also apologise in advance if this is relatively easy but I don't [think I] know the keyword to research constructing this. As I say, CASE is my best guess.
I'm having trouble working out how to manipulate CASE to fit what I'm trying to do. I do not need to return the values only the account_id from the valid row (only) that matches 4 or 5 of the given inputs.
I imagine that I could construct a layout that does this:
SELECT account_id CASE <if postcode_column=postcode_var> X=X+1
CASE <if surname_column=surname_var> X=X+1
...
...
WHERE X > 3
Is CASE the right idea?
If not, What is the process I need to use to achieve the desired results?
What is [another] MySQL keyword / syntax I need to research, if not CASE.
Here is your pseudo query:
SELECT account_id
FROM account
WHERE (postcode = 'pc')+
(postal_address = 'pa')+
(phone_number = '12345678901')+
(surname = 'sn')+
(forename= 'fn') > 3

Order all queries

I'm creating a new chat system with ColdFusion, but I'm having a lot of trouble with sorting out a little problem.
First of all I'll explain how the system works. When creating a new chat with someone, it creates a conversation row in the MySQL table conversations. After that, users can send each other messages. When sending a message, a row is inserted into the table conversations_messages with the timestamp, the user that sent the message, the message, and of course the id of the message. Sounds logical, but now comes the big problem: organizing all those messages.
Users can view their messages with others on a page, this is the code of that page:
// Check conversation ID based on page url
<cfif IsDefined('URL.chat') and URL.chat neq "">
// Load conversation based on page url
<cfquery name = "getconv" datasource = "#DSN#">
SELECT *
FROM `conversations`
</cfquery>
// Get all messages from this conversation
<cfoutput query="getconv">
<cfquery name = "getmessages" datasource = "#DSN#">
SELECT *
FROM `conversations_messages`
WHERE `conversation` = '#chat#'
ORDER BY `conversations_messages`.`id` DESC
</cfquery>
// Get messages sent by 'user_one'
<cfquery name = "my" datasource = "#DSN#">
SELECT *
FROM `conversations_messages`
WHERE `conversation` LIKE '#chat#'
AND `user` LIKE '#user.id#'
ORDER BY `conversations_messages`.`id` DESC
</cfquery>
// Get messages sent by 'user_two'
<cfquery name = "friend" datasource = "#DSN#">
SELECT *
FROM `conversations_messages`
WHERE `conversation` LIKE '#chat#'
AND `user` LIKE '#getconv.user_two#'
</cfquery>
<div class="content">
// Messages sent by 'user_one' aka. user that created conversation
You: <cfoutput><cfloop query="my">#my.message#<br></cfloop></cfoutput>
// Messages sent by 'user_two'
Friend: <cfoutput><cfloop query="friend">#friend.message#</cfloop></cfoutput>
</cfoutput>
</div>
</cfif>
This is how the results show up right now: (as you can see it's sorted by user)
I want it to be sorted by message ID, so it shows up like this:
I hope it's a bit clearer now!
Help would be appreciated!
(not sure why everyone is answering in comments rather than as "an answer"?)
The order that your results are returned from the DB are purely down to the order you tell them to be returned. So if you want them chronologically, then don't fetch them ordered by name; order them chronologically.
So don't get user1's messages, and then user2's messages, just get the messages for the entire conversation in conversation order. Then when you're outputting them, look at which user made which comment and do the "you" / "friend" stuff.
That said, I think the approach you're taking is less than ideal. What you should perhaps be doing is fetching the messages incrementally, as they happen, rather than waiting to get all of them (if you see what I mean). So on each person's UI get all the messages since the last displayed message, and display 'em (in chronological order), then wait for some polling interval, and then fetch the next lot of messages that have occurred since the last time (etc).
If you're using ColdFusion 10 all this stuff has already been done for you via the Web Sockets technology CF has. So that would be the way to go if that's an option for you.
(as Adam suggested here is an answer)
It seems to me that your query getmessages has what you are after. It looks to be all messages from this conversation = chat ordered by conversations_messages.id.
You really shouldn't query for * either, specify the needed columns only. You will get better performance that way.
Also, always use <cfqueryparam> tags in your cfquery blocks.
Also, you cannot nest <cfoutput> tags without a group attribute. Your code is already in a <cfoutput> so no need for another.
If you are on ColdFusion 10 I would definitely give #Adam's answer a look.