I am currently building a messaging feature and my goal is to get the last message between two users (a message inbox). And then when a user clicks on the last message, a full conversation between the two users will show. I currently have a messages table with the following data:
create table messages(
message_id serial primary key not null,
user_id_sender integer,
user_id_receiver integer,
subject varchar(100),
message text,
seen boolean default false,
date timestamptz
)
My question is, is it better to create a inbox table to log the last conversation between two users, or is there a query to find the last message between the two users and display that message with just the messages table. I have looked into and tried using CTE's, triggers and playing with SELECT DISTINCT that other have posted to no avail. I'm using React for my front end and get duplicate key issues with left joins with null values. Please I would like to know A.The best way to approach and normalize the data and B. Find the best query that would produce the desired result
Any help would be appreciated I'm just trying to find the right path and the best things to look into and learn to solve this kind of problem.
I have tried using CTEs, triggers, SELECT DISTINCT
If you are looking for a better option as per your question is it better to create a xxx table, then the answer is yes for retrieval of your latest message assuming you are storing only one record with the last message in that table xxx and the same record would be updated with the recent message always. You can update this table in your main table trigger (i.e. messages table) and the downside would be little performance hit during the insertion you can take a call on that after you check with a load test.
Coming to your second question is there a query to find the last message using the messages table; you can have a subquery to select the MAX of date from the messages table and then use that date in your main query like date = ( select max(date) to get the latest message. Make sure to create an index on the date column and also, for better performance add an additional where clause on the date column (for example date should be greater than the current date minus 30 days) in the main query.
Related
I'm in the process of building a database to keep track of loaning equipment. I'm trying to build a query that will display the latest record of each machines location.
Relevant table is:
Movements:
Movement ID (PK)
EntryDate (Automatically generated on record entry)
Serial (FK from a table called stock, with (Make, Model etc)
Location (Where the machine is)
Status (Things like: Available, Testing, Sold etc)
Current query is:
SELECT Movements.Serial, Max(Movements.EntryDateMovements) AS MaxOfEntryDateMovements
FROM Movements
GROUP BY Movements.Serial;
Which spits out the latest date of a record, and the serial associated with it.
What I need is the status to be shown in the results, but it still be grouped by the serial.
My issue is that when I try and add that, it either comes back with an error with about the expression not being part of the aggregate function, or I get more results than expected, as it no longer just keeps the results unique to the serial.
I'm pretty new Access, and have so far been able to muddle through guides, and books, and this site, to get everything else working, but i'm stuck at this hurdle.
Any help would be much appreciated.
Select top 1 *
from Movements
order by EntryDateMovements desc
This will give you everything for the newest record. This is TSQL but I think it carries over to Access.
Try this
Select t.serial,t.EntryDateMovements ,t.location, t.status
From movements as t
Inner join (SELECT Movements.Serial, Max(Movements.EntryDateMovements) AS MaxOfEntryDateMovements
FROM Movements
GROUP BY Movements.Serial) as MaxMovements on t.serial= MaxMovements.serial and t.EntryDateMovements=MaxMovements.MaxOfEntryDateMovements
I am new to SQL Server. I have been assigned to do some simple queries to start off, then eventually move on to more complex queries.
I have spent a lot of time on this website: http://www.w3schools.com and I understand it, I think, but then when I go back to my company's database, I find myself searching from many, many, different tables with different information.
For example, a table would say [Acct_Name] and the query comes back with not the correct account name (s) that I need. Any advice that you think might help me? Thank you.
It sounds like you are looking to limit your results to specific accounts. There are many ways to go about this, so no one will be able to give you a all encompassing answer but if you are looking to just pull a single account
SELECT * FROM (your table name) WHERE Acct_Name = 'the account name'
The * means you are selecting all columns in the table and your WHERE clause is where you set your search conditionals, like account name or by account ID. If you had a account creation date, you could get all accounts created on or before a date like this
SELECT * FROM (your table name) WHERE Created < '2016-06-01 00:00:00'
Replace the column name 'Created' with the column that holds the date field of account creation
Learning the WHERE clause and what you can do there to limit your results will get you on a solid footing to start, from there you will want to learn JOINs and how to link tables by primary keys.
Code academy has some great tutorials https://www.codecademy.com/learn/learn-sql
Please can you advise why we are seeing this error for a query we were previously able to run?
Error: Request was blocked to protect the systems operation. Please contact
We have tried running this query several times
Writing an email to the address returned:
you may not have permission to post messages to the group
I get this message when querying a 12TB table with around 25B rows. The query I am trying to run is selecting from one table, with a cross join on another table where two values in table A are between two values in table B, and I am doing a group by on two field. As mentioned before, all was working fine for the last 15 months until yesterday
To address your points in turn :
1 - Copy from shollyman's comment concerning your error:
The short answer: a cross join involving a table of that size is problematic given any reasonably sized second table. The message indicates that the BQ team is explicitly blocking this query due to its behavior.
2- I think you couldn't email at the address because it's a Google Group. You need to register to these first. There should be a way for you to do so. It's also possible (notice the error message says "may") that your message just needs to be accepted by a member of the group before it goes through.
3- If your issue is recent, it's most likely because you recently added enough data to one of your tables to make the cross join too big.
We have a SQL table that stores the date an email was created and then another table that gives details about that email (how long they spent writing the email, how long it was in a Draft mode etc). The join between the two tables is through a key.
The problem is, it only stores the date the email was created (entered into the system) and data is only written to the table when the email is completed (sent). So for yesterday, you may have 1000 emails completed that day, but their create date and time is varied. Also the create date time column is only in one table.
My method right now is to join the two tables, and in the where clause I calculate the completed date by adding the number of seconds of the email write time to the created date time.
WHERE DATEADD(s, ISNULL(a.emailwritetime,0), b.CreateDateTime) BETWEEN #start AND #end
(#start and #end are usually the previous day)
The tables have millions of rows, so expectedly, this takes a while to run and its hitting the production server to pull the data. Can anyone suggest a better/cleaner way of pulling the data? If you dont know what createdatetimes finished yesterday?
You should probably use a computed column for the value you're looking for.
I need to store an array of ints. Now my issue is, there's an operation that's done quite a few times so I'd like to limit it to one single query. In tha query, I would need to add an int to a certain int from the array.
It's for a timer of the time spent on a certain page. Currently it's just a general counter that counts for all the pages in the same field, so I only have to do
UPDATE user SET active = active+$totaltime WHERE id=:id
with the $totaltime being the time difference between last check and then. Now I'd like to store for certain pages seperately. The problem is I don't know exactly how many pages there will be. I thought about using serialize, but then I'd need to do 2 queries a lot of times which doesn't seem like a good solution.
Are there any other methods to do so?
What you need is a separate table for the levels which keeps track of active time associated with each user on each level.
Lets calls this table userlevels, and give it the following columns:
userid INT
levelid INT
active INT
The primary key should be a combination of the userid and leveid columns, since there can only be one entry for a particular combination of user and level.
Then when you want to update the amount of time a user has spent on a certain level, you would do something like:
INSERT INTO userlevels (userid,levelid,active)
VALUES (:userid,:levelid,$totaltime)
ON DUPLICATE KEY UPDATE active=active+$totaltime;
This creates a new entry in the table if the user has never been on that level before, or adds to the active time if there is already an entry.
This is mysql specific syntax, but the same thing can be achieved on other databases with different calls.