Latest results from db - mysql

I need display results from two joined tables only for the latest project. I have the following query:
SELECT project.id,
project.created,
COUNT(DISTINCT events.user_id) AS cnt
FROM project
JOIN events ON (events.project_id = project.id)
WHERE project.creator = $creatorID
AND events.user_id != $creatorID
ORDER BY project.created DESC
LIMIT 1
For some reason I keep on getting the first project... What am I missing here?

You're definitely on the right track. It seems you're missing a GROUP BY clause for your aggregate COUNT(). Try this:
SELECT
project.id,
project.created,
count(DISTINCT events.user_id) AS cnt
FROM project
JOIN events ON (events.project_id = project.id)
WHERE
project.creator = $creatorID
AND events.user_id != $creatorID
GROUP BY project.id, project.created
ORDER BY project.created DESC,
LIMIT 1

Related

MYSQL: Error Code: 1054. Unknown column in 'where clause'

I'm trying to pass a column from the outer query as shown below to the inner query in the WHERE clause and MySQL does not like it. I'm unsure how to rewrite this query to make it work.
The error message I am getting is Unknown column 'y.DateShipped' in where clause
What I am trying to do is to join to the row in the inner table with an EffectiveDate that is less than the DateShipped and also is the max EffectiveDate in the inner join (there can be multiple rows for the same group by with different EffectiveDate(s))
I would love to know how to get this working or rewrite it so that it will work. I am using MySQL 5.6, so I don't have window functions available otherwise I think that could work.
select
x.id,
y.id,
y.DateShipped
from Shipment y inner join
(select id, SourceId, DestinationId, SourcePPFContractId, EffectiveDate
from Relationship where EffectiveDate <= y.DateShipped order by
EffectiveDate desc limit 1) x
on x.DestinationId = y.DestinationCustomerId
and x.SourceId = y.OriginCustomerId
and x.SourcePPFContractId = y.OriginContractId;
The inner select (from Relationship) is executed first and then merged with the first select. That's why it doesn't work. You should move the DateShipped to the where clause of the first select:
select
x.id,
y.id,
y.DateShipped
from Shipment y inner join
(select id, SourceId, DestinationId, SourcePPFContractId, EffectiveDate
from Relationship order by
EffectiveDate desc limit 1) x
on x.DestinationId = y.DestinationCustomerId
and x.SourceId = y.OriginCustomerId
and x.SourcePPFContractId = y.OriginContractId
and x.EffectiveDate <= y.DateShipped;
You are attempting something called a lateral join -- and MySQL does not support those. Because you want only one column, you can use a correlated subquery:
select (select r.id
from Relationship r
where r.DestinationId = s.DestinationCustomerId and
r.SourceId = s.OriginCustomerId and
r.SourcePPFContractId = s.OriginContractId and
r.EffectiveDate <= s.DateShipped
order by r.EffectiveDate desc
limit 1
) as x_id,
s.id, s.DateShipped
from Shipment s ;
Note that I also changed the table aliases to be abbreviations for the table names -- so the query is easier to read.
you would need to list the shipment table in the sub query to be able to call it properly try:
select
x.id,
y.id,
y.DateShipped
from Shipment y inner join
(select id, SourceId, DestinationId, SourcePPFContractId, EffectiveDate
from Relationship, Shipment where EffectiveDate <= Shipment.DateShipped order by
EffectiveDate desc limit 1) x
on x.DestinationId = y.DestinationCustomerId
and x.SourceId = y.OriginCustomerId
and x.SourcePPFContractId = y.OriginContractId;

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

How to display only the multiple maximal values of my result table?

Using this MySQL queries on my database:
SELECT movie.name, SUM(heroes.likes) AS 'success'
FROM heroebymovie JOIN
heroes
ON heroes.ID = heroebymovie.heroID JOIN
movie
ON movie.ID = heroebymovie.movieID
GROUP BY movie.ID
ORDER BY SUM(heroes.likes) DESC
I obtain this result:
|name |success |
|Avengers 2 |72317559 |
|Avengers |72317559 |
|Captain America : Civil War|67066832 |
I would like to display only the movies with the highest number of “success” (in this case “Avengers 2” and “Avengers”).
Can someone explain the way of doing it?
A simple way is using an having clause that filter for the max value ( in this case the ordered list of sum desc limit 1)
SELECT movie.name, SUM(heroes.likes) AS success
FROM heroebymovie JOIN heroes ON heroes.ID = heroebymovie.heroID
JOIN movie ON movie.ID = heroebymovie.movieID
GROUP BY movie.ID
HAVING success = (
SELECT SUM(heroes.likes)
FROM heroebymovie JOIN heroes ON heroes.ID = heroebymovie.heroID
JOIN movie ON movie.ID = heroebymovie.movieID
GROUP BY movie.ID
ORDER BY SUM(heroes.likes) DESC
LIMIT 1
)
ORDER BY SUM(heroes.likes) DESC
You are looking for a limit, but want to consider ties. MySQL supports the LIMIT clause, but unfortunately no accompanying ties expression.
In standard SQL you would simply add
FETCH 1 ROW WITH TIES;
and be done with it. (SQL Server does the same with TOP(1) WITH TIES.)
Another way would be to use standard SQL's MAX OVER: MAX(SUM(heroes.likes)) OVER() and only keep rows where the sum matches the maximum. Or use RANK OVER. But again, MySQL doesn't support either of these.
So your main option is to execute the query twice, like in this pseudo code:
select sum ... having sum = (select max(sum) ...)
An easy way to get the max of the sums in MySQL is to order by sums descending and limit the results to one row.
SELECT m.name, SUM(h.likes) AS "success"
FROM heroebymovie hm
JOIN heroes h ON h.ID = hm.heroID
JOIN movie m ON m.ID = hm.movieID
GROUP BY m.ID
HAVING SUM(h.likes) =
(
SELECT SUM(h2.likes)
FROM heroebymovie hm2
JOIN heroes h2 ON h2.ID = hm2.heroID
GROUP BY hm2.movieID
ORDER BY SUM(h2.likes) DESC
LIMIT 1
);

How to avoid multiple results from sub query

Hi guys i am new bie to MySQL,this might be
easier to question but i am totally new for mysql.
i have two tables order and shops the Desc of two
tables look like this....
OrdersTable.
order id:
ordername:
shopnum(fk)
Shopstable*
shopname:
shopnum(pk):
i am using sub query like this,to get the shops name which have most number of orders....
like...19 xyzshop
. 13 hjjddshop
. 6 reebok shop
select shopname
from shopstable
where shopnum in
(select count(orderid) as highest ,shopnum
from orderTable
group by shopnum)
it throws error,display column should be 1,its because the subquery is returning 2 results...so how do i avoid that and get the appropriate result...help will be appreciated...:):)
It's not complaining because the subquery returns 2 results but two columns. But even if it did only return a single column, it would return 2 results and the main query would do the same.
No need for a subquery in any case:
SELECT s.shopname
FROM Shopstable s
JOIN OrdersTable o ON s.shopnum=o.shopnum
GROUP BY s.shopname
ORDER BY count(*) DESC
LIMIT 1
Use this:
select shopname
from shopstable
where shopnum in
(select shopnum
from orderTable
group by shopnum
order by count(*) DESC
limit 1)
remove count(orderid) as highest , in your query. you should only select one column in your subquery
i think you want something like this...
SELECT shopname, count(*) as highest
FROM shopstable
INNER JOIN orderTable ON (shopstable = orderTable.shopname)
GROUP BY shopstable.shopname
i think this is the result you want?

How do I get more than one column from a SELECT subquery?

Here is my problem :
I have 3 tables : account, account_event and account_subscription
account contains details like : company_name, email, phone, ...
account_event contains following events : incoming calls, outgoing calls, visit, mail
I use account_subscription in this query to retrieve the "prospects" accounts. If the account does not have a subscription, it is a prospect.
What I am using right now is the following query, which is working fine :
SELECT `account`.*,
(SELECT event_date
FROM clients.account_event cae
WHERE cae.account_id = account.id
AND cae.event_type = 'visit'
AND cae.event_done = 'Y'
ORDER BY event_date DESC
LIMIT 1) last_visit_date
FROM (`clients`.`account`)
WHERE (SELECT count(*)
FROM clients.account_subscription cas
WHERE cas.account_id = account.id) = 0
ORDER BY `last_visit_date` DESC
You can see that it returns the last_visit_date.
I would like to modify my query to return the last event details (last contact). I need the event_date AND the event_type.
So I tried the following query which is NOT working because apparently I can't get more than one column from my select subquery.
SELECT `account`.*,
(SELECT event_date last_contact_date, event_type last_contact_type
FROM clients.account_event cae
WHERE cae.account_id = account.id
AND cae.event_done = 'Y'
ORDER BY event_date DESC
LIMIT 1)
FROM (`clients`.`account`)
WHERE (SELECT count(*)
FROM clients.account_subscription cas
WHERE cas.account_id = account.id) = 0
ORDER BY `last_visit_date` DESC
I tried a lot of solutions around joins but my problem is that I need to get the last event for each account.
Any ideas?
Thank you in advance.
Jerome
Get a PRIMARY KEY in a subquery and join the actual table on it:
SELECT a.*, ae.*
FROM account a
JOIN account_event ae
ON ae.id =
(
SELECT id
FROM account_event aei
WHERE aei.account_id = a.id
AND aei.event_done = 'Y'
ORDER BY
event_date DESC
LIMIT 1
)
WHERE a.id NOT IN
(
SELECT account_id
FROM account_subscription
)
ORDER BY
last_visit_date DESC
Try moving the subquery to from part and alias it; it will look as just another table and you'll be able to extract more than one column from it.