I'm not good at Mysql expressions, so here is a quick question that I'm trying to get my head around. I would like to reverse the order of the GROUP BY expression so that I can get the last entry by the user.
I managed to find good examples around the internet, but I couldn't implement them with my expression without receiving an error. Thanks guys!
SELECT messages.conv, messages.from_user, messages.to_user,
messages.content, messages.date_posted, messages.note_read,
messages.active, users.thumb, users.name, users.id
FROM `messages`
INNER JOIN `users`
ON messages.from_user = users.id
WHERE messages.from_user = 1
OR messages.to_user = 1
GROUP BY messages.conv
ORDER BY date_posted ASC
EDIT: I apparently misunderstood your requirement, your current query will return a pseudo-random row due to your GROUP BY not having any aggregates, what you want is the last row for each conversation which would be something more like (assuming messages, like users, has an autoincrementing primary key called id);
SELECT messages.conv, messages.from_user, messages.to_user,
messages.content, messages.date_posted,
messages.note_read, messages.active, users.thumb,
users.name, users.id FROM `messages`
INNER JOIN `users`
ON messages.from_user = users.id
WHERE messages.id IN
(SELECT MAX(id) FROM messages
WHERE messages.from_user = 1 OR messages.to_user = 1
GROUP BY conv);
SQLFiddle here.
Related
My query is below
SELECT *
FROM
(
SELECT
usr.*,
messages.message_text, messages.message_id
FROM
`user` as usr
LEFT JOIN
(
SELECT
message.*
FROM
message AS message
ORDER BY
message.updated_at
DESC
) AS messages
ON
`usr`.`user_id` = `messages`.`sender_id` OR `usr`.`user_id` = `messages`.`receiver_id`
WHERE
`usr`.`is_delete` = 0 AND `usr`.`is_active` = 1
ORDER BY
messages.updated_at
DESC
) AS result
GROUP BY
result.user_id
if i remove the group by then it work well , but i want the result with group by Please Help.
I have one message table in that i have saved the sender id and receiver id, both id have foreign key with user table and i want the recent message send by user and user details
So for latest message i am using order by desc and after getting all the messages with descending order i am using group by but it is not working.
It was very hard making the table schemas and the data insert in them which would act like your scenario. So next time, please provide a fiddle link to your schema/situation.
Here were the issues in your query:
You dont need a subquery after LEFT JOIN
ORDER BY clause is always after GROUP BY
You must mention all the columns that you are SELECTing in the GROUP BY clause.
Tweaked your query a bit:
SELECT *
FROM
(
SELECT
usr.*,
messages.message_text, messages.message_id, messages.updated_at
FROM
user as usr
LEFT JOIN message messages
--(
-- SELECT
-- message.*
-- FROM
-- message AS message
-- ORDER BY
-- message.updated_at
-- DESC
--) AS messages
ON
usr.user_id = messages.sender_id OR usr.user_id = messages.receiver_id
WHERE
usr.is_delete = 0 AND usr.is_active = 1
--ORDER BY
--messages.updated_at
--DESC
) AS result
GROUP BY
result.user_id,result.name,result.is_delete,result.is_active,result.message_text,result.message_id,updated_at
ORDER BY
result.updated_at
DESC
Hope it helps :)
I have a question about a SQL, I have never worked with the select sub and I ended up getting lost with it.
Meu SQL:
SELECT CLI.id, CLI.nome, CLI.senha, CLI.email, CLI.cpf, CLI.celular, CLI.data_nasc, CLI.genero, CLI.data_cadastro, CLI.status, CLI.id_socket, ATEN.mensagem, ARQ.nome AS foto, ATEN.data_mensagem
FROM ut_clientes AS CLI
LEFT JOIN ut_arquivos AS ARQ ON (ARQ.id_tipo = CLI.id AND ARQ.tipo = "ut_clientes")
INNER JOIN ut_atendimentos AS ATEN ON (ATEN.id_usuario_envio = CLI.id)
WHERE ATEN.id_usuario_envio != 59163
GROUP BY CLI.id
ORDER BY ATEN.data_mensagem
DESC
Well, what I would like to do is group the messages according to the customer ID and bring only the last message recorded in the database according to the data_mensagem.
I have tried in many ways but always the last one that is displayed is the first message inserted in DB.
If anyone can help me, I'll be grateful. Thank you guys!
This may help you... I am using a join to a pre-query (PQ alias). This query just goes to your messages and grabs the client ID and the most recent based on the MAX(). By doing the group by here, it will at most return 1 record per client. I also have the WHERE clause to exclude the one ID you listed.
From THAT result, you do a simple join to the rest of your query.
SELECT
CLI.id,
CLI.nome,
CLI.senha,
CLI.email,
CLI.cpf,
CLI.celular,
CLI.data_nasc,
CLI.genero,
CLI.data_cadastro,
CLI.status,
CLI.id_socket,
ATEN.mensagem,
ARQ.nome AS foto,
PQ.data_mensagem
FROM
ut_clientes AS CLI
LEFT JOIN ut_arquivos AS ARQ
ON CLI.id = ARQ.id_tipo
AND ARQ.tipo = "ut_clientes"
INNER JOIN
( select
ATEN.id_usuario_envio,
MAX( ATEN.data_mensagem ) as MostRecentMsg
from
ut_atendimentos AS ATEN
where
ATEN.id_usuario_envio != 59163
group by
ATEN.id_usuario_envio ) PQ
ON CLI.id = PQ.id_usuario_envio
GROUP BY
CLI.id
ORDER BY
PQ.data_mensagem DESC
I'm struggling to make a query efficient enough. I'm using Doctrine2 ORM (the query is build with QueryBuilder) and part of my query is running very slow - takes about 4s with table of 5000 rows.
This is the relevant part of db schema:
TABLE user
id (primary)
... (plenty of rows, not relevant to the query)
TABLE slot
id (primary)
user_id (foreign for user)
date (datetime)
And this is how my query looks like (it's the basic version, there's a lot of filters to be applied, but these work like fine for now)
SELECT
u.id AS uid,
COUNT(DISTINCT s_order.id) AS sclr_1,
COUNT(DISTINCT s_filter.id) AS sclr_2
FROM
user u
LEFT JOIN slot s_order ON (s_order.user_id = u.id)
LEFT JOIN slot s_filter ON (s_filter.user_id = u.id)
WHERE
(
(
(
s_order.date BETWEEN ?
AND ?
)
AND (
s_filter.date BETWEEN ?
AND ?
)
)
AND (u.deleted_at IS NULL)
)
AND u.userType IN ('2')
GROUP BY
u.id
HAVING
sclr_2 > 0
ORDER BY
sclr_1 DESC
LIMIT
12
Let me explain what I'm trying to achieve here:
I need to filter users who has any slots between 1 week ago and 1 week ahead, then order them by count of slots available between now and 1 week ahead. The part of query causing issues is LEFT JOIN of s_filter and I'm wondering whether perhaps there's a way to improve the performance of that query?
Any help appreciated really, even if it's only plain SQL I'll try to convert it to DQL myself!
#UPDATE
Just an additional info that I forgot, the LIMIT in query is for pagination purposes!
#UPDATE 2
After a while of tweaking the query I figured out that I can use JOIN for filtering instead of LEFT JOIN + COUNT, so my query does look like that now:
SELECT
u.id AS uid, COUNT(DISTINCT s_order.id) AS ordinal
FROM
langu_user u
LEFT JOIN
slot s_order ON (s_order.user_id = u.id) AND s_order.date BETWEEN '2017-02-03 14:03:22' AND '2017-02-10 14:03:22'
JOIN
slot s_filter ON (s_filter.user_id = u.id) AND s_filter.date BETWEEN '2017-01-27 14:03:22' AND '2017-02-10 14:03:22'
WHERE
u.deleted_at IS NULL
AND u.userType IN ('2')
GROUP BY u.id
ORDER BY ordinal DESC
LIMIT 12
And it went down from 4.1-4.3s to 3.6~
I've got a table of users (1,000s) and a table of user messages (100,000s). I want a fast way of getting all users and their most recent message.
What I'm currently using is something like...
SELECT
u.id, u.name,
(
SELECT note FROM msgs
WHERE msgs.uID=u.id
ORDER BY created_date DESC
LIMIT 1
) as note
FROM users u
Right now if I limit that to 20 users, it takes 2.5s ... 200 users takes 45s.
(I already have an INDEX on msgs.uID and msgs.created_date.)
What am I doing wrong? I need a much faster query.
I searched before posting (with no luck), but found this solution in the "related" sidebar just after posting.
SELECT u.id, u.first_name, msgs.note
FROM users u
JOIN (
SELECT MAX(created_date) max_date, user_id
FROM msgs
GROUP BY user_id
) msgs_max ON (msgs_max.user_id = u.id)
JOIN msgs m ON (msgs.created_date = msgs_max.max_date AND u.id = msgs.user_id)
Considerably better, but still ~1.3s on my tables. Can't MySQL do this much faster?
select users.*, msgs2.* from users
inner join
(
select msgs.* from msgs
inner join
(
select max(created_date) as dt, user_id from msgs
group by user_id
) last_dt
on
msgs.user_id = last_dt.user_id
and
msgs.created_date = last_dt.dt
) msgs2
on
users.id = msgs2.user_id
Try this, I am sorry if this may be has some syntax error, or may be also works slow, I write this query directly, without any test.
Just try.
Solution with just two joins
SELECT u.id,u.name,msgs_max.note FROM users u JOIN
(SELECT m1.uID, m1.note FROM msgs m1 LEFT JOIN msgs m2
ON (m1.created_date < m2.created_date
AND m1.uID = m2.uID)
WHERE m2.id IS NULL) msgs_max
ON u.uID=msg_max.uID
Reference: https://stackoverflow.com/a/123481/2180715
While working on a system I'm creating, I attempted to use the following query in my project:
SELECT
topics.id,
topics.name,
topics.post_count,
topics.view_count,
COUNT( posts.solved_post ) AS solved_post,
(SELECT users.username AS posted_by,
users.id AS posted_by_id
FROM users
WHERE users.id = posts.posted_by)
FROM topics
LEFT OUTER JOIN posts ON posts.topic_id = topics.id
WHERE topics.cat_id = :cat
GROUP BY topics.id
":cat" is bound by my PHP code as I'm using PDO. 2 is a valid value for ":cat".
That query though gives me an error: "#1241 - Operand should contain 1 column(s)"
What stumps me is that I would think that this query would work no problem. Selecting columns, then selecting two more from another table, and continuing on from there. I just can't figure out what the problem is.
Is there a simple fix to this, or another way to write my query?
Your subquery is selecting two columns, while you are using it to project one column (as part of the outer SELECT clause). You can only select one column from such a query in this context.
Consider joining to the users table instead; this will give you more flexibility when selecting what columns you want from users.
SELECT
topics.id,
topics.name,
topics.post_count,
topics.view_count,
COUNT( posts.solved_post ) AS solved_post,
users.username AS posted_by,
users.id AS posted_by_id
FROM topics
LEFT OUTER JOIN posts ON posts.topic_id = topics.id
LEFT OUTER JOIN users ON users.id = posts.posted_by
WHERE topics.cat_id = :cat
GROUP BY topics.id
In my case, the problem was that I sorrounded my columns selection with parenthesis by mistake:
SELECT (p.column1, p.column2, p.column3) FROM table1 p WHERE p.column1 = 1;
And has to be:
SELECT p.column1, p.column2, p.column3 FROM table1 p WHERE p.column1 = 1;
Sounds silly, but it was causing this error and it took some time to figure it out.
This error can also occur if you accidentally use commas instead of AND in the ON clause of a JOIN:
JOIN joined_table ON (joined_table.column = table.column, joined_table.column2 = table.column2)
^
should be AND, not a comma
This error can also occur if you accidentally use = instead of IN in the WHERE clause:
FOR EXAMPLE:
WHERE product_id = (1,2,3);
COUNT( posts.solved_post ) AS solved_post,
(SELECT users.username AS posted_by,
users.id AS posted_by_id
FROM users
WHERE users.id = posts.posted_by)
Well, you can’t get multiple columns from one subquery like that. Luckily, the second column is already posts.posted_by! So:
SELECT
topics.id,
topics.name,
topics.post_count,
topics.view_count,
posts.posted_by
COUNT( posts.solved_post ) AS solved_post,
(SELECT users.username AS posted_by_username
FROM users
WHERE users.id = posts.posted_by)
...
I got this error while executing a MySQL script in an Intellij console, because of adding brackets in the wrong place:
WRONG:
SELECT user.id
FROM user
WHERE id IN (:ids); # Do not put brackets around list argument
RIGHT:
SELECT user.id
FROM user
WHERE id IN :ids; # No brackets is correct
This error can also occur if you accidentally miss if function name.
for example:
set v_filter_value = 100;
select
f_id,
f_sale_value
from
t_seller
where
f_id = 5
and (v_filter_value <> 0, f_sale_value = v_filter_value, true);
Got this problem when I missed putting if in the if function!
Another place this error can happen in is assigning a value that has a comma outside of a string. For example:
SET totalvalue = (IFNULL(i.subtotal,0) + IFNULL(i.tax,0),0)
(SELECT users.username AS posted_by,
users.id AS posted_by_id
FROM users
WHERE users.id = posts.posted_by)
Here you using sub-query but this sub-query must return only one column.
Separate it otherwise it will shows error.
I also have the same issue in making a company database.
this is the code
SELECT FNAME,DNO FROM EMP
WHERE SALARY IN (SELECT MAX(SALARY), DNO
FROM EMP GROUP BY DNO);