Doctrine left join Many to one - php

I have a table client and table client_evolution, with OneToMany relationship. In client_evolution table I have 3 entries for current client. Pulling data with Left Join I get always the first entry with smallest id from client_evolution , what I need is the latest row. I have tried to do subselect but it didn't work.
->addSelect('(
SELECT ce.id
FROM ClientEvolution cev
WHERE cev.client = c.id
GROUP BY cev.client
ORDER BY cev.id DESC) AS cevol')
I need more than one field from this table.
Any help please.

The GROUP BY is why you are getting only one entry per client also your SELECT is missing the client table. This will give you all the fields between the two tables in order of client ids. To only get the latest row for each client id, please look at MySQL Group By to display latest result
->addSelect('(
SELECT *
FROM ClientEvolution cev, Client c
WHERE cev.client = c.id
ORDER BY cev.client, cev.id DESC)')

Related

JOIN - Select columns/details with different criteria than COUNT

I have a chat system. There are 3 tables:
data_chats - holds the IDs of the chats themselves. This is where you mark a chat as deleted.
data_chat_parties - holds the member or team ID that is included in chat along with chat permissions, who they were invited by, etc
data_chat_messages - holds the actual messages of chats
With my query, I am trying to fetch the info from data_chat_parties related to the party requesting this information (ie currently logged in user), but also get the total number of chat parties in the chat.
SELECT
data_chats.id AS chat,
data_chats_parties.*,
COUNT(data_chats_parties.id) AS total_parties,
data_chats_messages.created AS last_message_created,
data_chats_messages.author AS last_message_author,
data_chats_messages.author_type AS last_message_author_type,
data_chats_messages.message AS last_message
FROM data_chats
LEFT JOIN data_chats_parties ON data_chats_parties.chat=data_chats.id
LEFT JOIN data_chats_messages ON data_chats_messages.chat=data_chats.id AND data_chats_messages.active=1
WHERE
data_chats.active=1 AND
data_chats_parties.member=1 AND
data_chats_parties.status >= 1
GROUP BY data_chats_parties.chat
ORDER BY last_message_created DESC
This all works fine, except that total_chat_parties always returns 1, presumably because it's only matching the record of data_chats_parties.member=1. How would I fetch the party record specific to this user but at the same time, fetch the total number of parties for this chat?
You should use a correlated query :
SELECT data_chats.id AS chat,
(SELECT COUNT(data_chats_parties.id) FROM data_chats_parties
WHERE data_chats_parties.chat = data_chats.id) AS total_parties,
data_chats_messages.created AS last_message_created,
data_chats_messages.author AS last_message_author,
data_chats_messages.author_type AS last_message_author_type,
data_chats_messages.message AS last_message
FROM data_chats
LEFT JOIN data_chats_messages
ON data_chats_messages.chat = data_chats.id
AND data_chats_messages.active = 1
AND data_chats_parties.member = 1
AND data_chats_parties.status >= 1
WHERE data_chats.active = 1
ORDER BY last_message_created DESC
Another thing is the conditions on the WHERE clause, you can filter the RIGHT table of a LEFT JOIN in the WHERE clause, those condition should only be specified in the ON clause.
You also group by a column from the RIGHT table - this is not suggested at all! Either use an inner join, or group by another field.
you may be able to use a subquery in the select statement to give you the desired count.
(select COUNT(data_chats_parties.id) from data_chats_parties where data_chats_parties.chat=data_chats.id) AS total_parties,
Also you can then remove the line
LEFT JOIN data_chats_parties ON data_chats_parties.chat=data_chats.id
Hopefully I've typed that all correctly =)

Multiple table select grouped query

We need to grab the last and newest 20 entries from different tables. However, the GROUP BY statement skips records because we are working with LEFT JOIN on tables.
All these records are linked to unique persons in another table. We store these person's id's in an array for more queries later.
We have a few tables (in which all those person id's are stored) and we want to get them sorted and grouped.
The tables are like this:
SELECT lastRecord+personID FROM t1
SELECT lastRecord+personID FROM t2
SELECT lastRecord+personID FROM t3
SELECT lastRecord+personID FROM t4
WHERE t5.Essential_Column_Name = '1'
GROUP BY personID
ORDER BY 'all the latest entries'
LIMIT 20
With that, the relevance of all the latest entries should be equal.
We do have a timestamp column as well. Perhaps that might work better.
Any input is highly appreciated!
For people looking for an answer on this; this is the right post, answer and update to this Q:
UNION mysql gives weird numbered results
With thanks to all for the ideas and providing the paths to the right solution.

how to write mysql query with join and still display partial info if a record from one table is deleted?

i have a join query that displays info from 2 tables, but if a record is deleted from one of the tables, the joined record doesn't show. i still want to display the joined record but with the data from the first table showing and the info with the second table missing.
here is the query i'm working with.
$result = mysql_query("SELECT user_groups.*, pricing_groups.* FROM user_groups inner join pricing_groups on user_groups.pricing_group_id = pricing_groups.id LIMIT 2,18446744073709551615")
i'm limiting it by 2. i still want that in next version.
if record from pricing_groups is deleted that is attached to a record from user_groups, it's ok to show the user group info. in fact, i want it to display the user group info. but if it's the other way around...if a user group is deleted, then it's ok not to show either the user group info or pricing group info.
To include all records from user_groups you would need to use a LEFT JOIN like so:
SELECT ug.*, pg.*
FROM user_groups AS ug
LEFT JOIN pricing_groups AS pg
ON ug.pricing_group_id = pg.id
LIMIT 2,18446744073709551615
The LEFT JOIN returns all rows from the left table (user_groups), with the matching rows from the right table (pricing_groups). The result is NULL in the right side when there is no match.

Get and order based on most recent entry while in multiple mysql joins

I have the following statement that finds all the players of a team in the current season. The players are ordered by their handicap. If their handicaps are the same they are ordered by the oldest added_date, meaning newer members are lower down the list.
SELECT players.playerid_p,
players.fname,
players.sname,
players.tel,
players.mob,
players.email,
season_players.captain
FROM season_players
LEFT JOIN players ON (season_players.playerid_f = players.playerid_p)
LEFT JOIN handicaps ON (handicaps.playerid_f = players.playerid_p)
WHERE season_players.seasonid_f = '$currentSeason'
AND season_players.teamid_f = '".$row["teamid_p"]."'
GROUP BY players.playerid_p
ORDER BY handicaps.handicap ASC, handicaps.added_date ASC
The handicaps table can have multiple entries per player for any reviews they have had.
I can't figure out how to make the latest handicap to be used for the ordering (something maybe to do with MAX on added_date?) yet at the same time if two or more handicaps are the same it order them by oldest registered first based on added_date.
In stead of trying to figure out how to satisfy your needs in current query, wouldn't it be an option to create a separate table, let's say "Handicaps_latest", which only stores player_id and required info of latest review. The reason for doing this is because you are only trying to get(columns in your select clause) the information about players and nothing really needed from handicaps table. In this case, a handicaps table with multiple entries per player might not be a good table to join. But considering that those data might be required in other logic, so leave them there and create a branch new table only storing latest review data could be an option for your case. But it requires some extra work apparently, that is, whenever you insert a new entry into your original handicpas table, a particular entry in handicaps_latest needs to be updated.
SELECT x.*
FROM my_table x
JOIN
( SELECT id,MAX(other_column) max_other_column FROM my_table GROUP BY id) y
ON y.id = x.id
AND y.max_other_column = x.other_column;

Pulling most recent result from a one to many join in mysql

I am working on a web app and I have a database with two tables. One of them is called entities and the other is activities. It is a one to many relationship where there are many entities in the activities table. The activities table has a date associated with it and I want to pull results based on certain entity id's but I only want to pull the most recent activity (by its date). So basically, I only want one return per entity. There must be a way to do this in mysql without parsing out the data with php. I want to make the app as fast as possible. Any help would be greatly appreciated.
Guessing at field names ...
SELECT
e.*, a.*
FROM
(SELECT
MAX(ActivityID) ActivityID,
EntityID
FROM
Activity
GROUP By
EntityID) maxActivity
INNER JOIN Activity a
ON maxActivity.ActivityID = a.ActivityID
INNER JOIN Entity e
ON e.EntityID = a.EntityID
Or if ID isn't always the latest and you really want date (assuming two activities can't share the same date)
SELECT
e.*, a.*
FROM
(SELECT
MAX(Date) Date,
EntityID
FROM
Activity
GROUP By
EntityID) maxActivity
INNER JOIN Activity a
ON maxActivity.Date = a.Date
and maxActivity.EntityID = a.EntityID
INNER JOIN Entity e
ON e.EntityID = a.EntityID
I would say, create a linking table through a PK / FK relationship.
So for instance:
[entities table] ------ [ent_activities] --- [activities] , especially since the two data is so intertwined.
1:M is a horrible data integrity issue and even more so when you have 10s, even hundreds of 1:M throughout.
Good luck

Categories