MySQL - Count on a join - mysql

I'm trying to count freelanceFeedback's and order by the count like this:
$sql = "SELECT authentication.*, (SELECT COUNT(*) FROM freelanceFeedback) as taskscount FROM authentication
LEFT JOIN freelanceFeedback
ON authentication.userId=freelanceFeedback.FK_freelanceWinnerUserId
WHERE `FK_freelanceProvider`=$what
ORDER BY taskscount DESC";
But I'm having multiple outputs if the user has multiple feedbacks and it's not ordering by the taskscount.
I can't figure out what the 'tweet' is wrong..
** UPDATE **
I think I've got it myself:
$sql = "SELECT DISTINCT authentication.*,
(SELECT COUNT(*) FROM freelanceFeedback
WHERE FK_freelanceWinnerUserId=userId
) as taskscount
FROM authentication
WHERE `FK_freelanceProvider`=$what
ORDER BY taskscount DESC";
This is only outputting 1 user and ORDERING by the amount of feedbacks.

When you use COUNT(), you also need to use GROUP BY:
SELECT authentication.userId,
COUNT(freelanceFeedback.id) AS taskscount
FROM authentication
LEFT JOIN freelanceFeedback
ON authentication.userId = freelanceFeedback.FK_freelanceWinnerUserId
WHERE `FK_freelanceProvider`= $what
GROUP BY authentication.userId
ORDER BY taskscount DESC
However, this will only work if you are not doing SELECT * (which is bad practice anyway). Everything that's not in the COUNT bit needs to go into GROUP BY. If this includes text fields, you'll not be able to do it, so you'll need to do a JOIN to a subquery. MySQL won't complain if you don't but it can seriously slow things down and other DBs will throw an error, so best to do it right:
SELECT authentication.userId,
authentication.textfield,
authentication.othertextfield,
subquery.taskscount
FROM authentication
LEFT JOIN (SELECT freelanceFeedback.FK_freelanceWinnerUserId,
COUNT(freelanceFeedback.FK_freelanceWinnerUserId) AS taskscount
FROM freelanceFeedback
GROUP BY FK_freelanceWinnerUserId) AS subquery
ON authentication.userId = subquery.FK_freelanceWinnerUserId
WHERE authentication.FK_freelanceProvider = $what
ORDER BY subquery.taskscount DESC
It's not clear what table the FK_freelanceProvider is part of so I've assumed it's authentication.

Related

Working with SELECT and SUB SELECT in MySQL

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

Weird issue with a sql query [duplicate]

I am creating an SQL query in Hibernate for a messaging component. The idea is that I am querying to get conversations for a user, sorted on the date of the last message sent.
I have two tables:
conversations
messages
In my select query I am attempting something like this but the ordering never happens on the last message sent.
String sql =
"SELECT * FROM conversations " +
"JOIN messages ON messages.conversation_id = conversations.id "+
"WHERE (conversations.creator_id = :userId OR conversations.to_id = :userId)" +
"GROUP BY messages.conversation_id "+
"ORDER BY messages.created DESC";
The issue is due to a MySQL-specific extension to the behavior of the GROUP BY clause. Other databases would throw an error... something akin to on-aggregate in SELECT list". (We can get MySQL to throw a similar error, if we include ONLY_FULL_GROUP_BY in sql_mode.)
The issue with the expression messages.created is that refers to a value from an indeterminate row in the GROUP BY. The ORDER BY operation occurs much later in the processing, after the GROUP BY operation.
To get the "latest" created for each group, use an aggregate expression MAX(messages.created).
To get the other values from that same row, is a little more complicated.
Assuming that created is unique within a given conversation_id group (or, if there's no guaranteed that it's not unique, and you are okay with returning multiple rows with the same value for created...
To get the latest created for each conversation_id
SELECT lm.conversation_id
, MAX(lm.created) AS created
FROM conversation lc
JOIN message lm
ON lm.conversation_id = lc.id
WHERE (lc.creator_id = :userId OR lc.to_id = :userId)
GROUP BY lm.conversation_id
You can use that as an inline view, to get the whole row with that latest created
SELECT c.*
, m.*
FROM ( SELECT lm.conversation_id
, MAX(lm.created) AS created
FROM conversation lc
JOIN message lm
ON lm.conversation_id = lc.id
WHERE (lc.creator_id = :userId OR lc.to_id = :userId)
GROUP BY lm.conversation_id
) l
JOIN conversation c
ON c.id = l.conversation_id
JOIN messages m
ON m.conversation_id = l.conversation_id
AND m.created = l.created
WHERE (c.creator_id = :userId OR c.to_id = :userId)
NOTES:
You can add an ORDER BY clause to order the rows returned however you need.
The WHERE clause on the outer query is likely redundant, and unnecessary.
We prefer to avoid using SELECT *, and prefer to explicitly list the expressions to be returned.

MySQL Query, multiple counts and sums

I have a MySQL query that outputs to a php table but I'm having issues in joining two tables that both use a COUNT:
$query = "SELECT mqe.registration,
COUNT(*) AS numberofenqs,
COUNT(DISTINCT ucv.ip) AS unique_views,
SUM(ucv.views) AS total_views
FROM main_quick_enquiries AS mqe
LEFT OUTER JOIN used_car_views AS ucv
ON ucv.numberplate = mqe.registration
WHERE mqe.registration IS NOT NULL
GROUP BY mqe.registration ORDER BY numberofenqs DESC";
The query runs, but the number within the numberofenqs column is always wrong as i know from performing that query on its own that it comes in with the correct result:
SELECT registration, COUNT(*) AS numberofenqs FROM main_quick_enquiries GROUP BY registration ORDER BY numberofenqs DESC
Why is the COUNT(*) not working correctly in top query code and where is it getting the figures from?
it could be because of LEFT OUTER JOIN ...
Try to run this:
SELECT registration
, count(*)
FROM main_quick_enquiries
GROUP BY registration
and compare it with this result
SELECT mqe.registration
, count(*)
FROM main_quick_enquiries mqe
LEFT OUTER JOIN used_car_views ucv
ON ucv.numberplate = mqe.registration
GROUP BY mqe.registration
There could be a problem :) in duplicity rows... try to find one specific registration number, and compare the details of both query
SELECT *
FROM main_quick_enquiries
WHERE registration = XXXX
+
SELECT *
FROM main_quick_enquiries mqe
LEFT OUTER JOIN used_car_views ucv
ON ucv.numberplate = mqe.registration
WHERE registration = XXXX
you should see the diffs
Thanks All, but I think I've nailed it with COUNT(DISTINCT mqe.id) instead of COUNT(*).

GROUP BY not sorting properly when using joins

I want to see only one record from the joined table fr_movements with the newest sched_date yet I am always getting the oldedst sched_date. Since the ORDER BY sorts by the sched_date and I am grouping by the people.ID I am getting only one record from fr_movements as expected, just the wrong one.
SELECT `fr_movements`.`ID`, fr_movements_list.movement_type,
fr_movements.sched_date, fr_movements.comp_date, people.firstname, people.lastname
FROM fr_movements
LEFT JOIN people ON people.ID = fr_movements.`people_id`
LEFT JOIN fr_movements_list ON (fr_movements.move_type_id = fr_movements_list.ID)
WHERE fr_movements.org_id = 25 AND fr_movements.move_type_id IN (54,53,52,51,50,55)
GROUP BY people.ID
ORDER BY people.org_name, fr_movements.sched_date ASC
Anybody know how to do this properly?
as #bluefeet mentioned
you are using GROUP BY incorrectly. GROUP BY is supposed to be used with an aggregate function
You need to put all columns after GROUP BY, but it is complicated. I think DISTINCT might help you. like this:
SELECT *
FROM
(
SELECT DISTINCT people.org_name, `fr_movements`.`ID`, fr_movements_list.movement_type,
fr_movements.sched_date, fr_movements.comp_date, people.firstname, people.lastname
FROM fr_movements
LEFT JOIN people ON people.ID = fr_movements.`people_id`
LEFT JOIN fr_movements_list ON (fr_movements.move_type_id = fr_movements_list.ID)
WHERE fr_movements.org_id = 25
AND fr_movements.move_type_id IN (54,53,52,51,50,55)
) x
ORDER BY org_name, sched_date ASC
If not works, would you post your data & schema into sqlfiddle? That makes us happy.

MySQL - Operand should contain 1 column(s)

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);