retrieve the most recent date within a query - php

I was able to fix my previous query, however the results retrieve contains duplicates. I want to retrieve the latest record.
For example:
id | firstname | lastname | email | date
1 | steven | smith | steven#gmail.com 2013-06-10 04:01:25
2 | Bill | Johnson | bill#gmail.com | 2014-06-10 04:01:25
3 | steven | smith | steven#gmail.com | 2014-10-10 12:01:25
The return result should be the row with IDs 2 and 3
THe ID 1 should be not returned as the date is older than the ID 3 date
How can I add this to the query below ?
SELECT
users.firstname,
users.lastname,
DISTINCT(users.email),
users.pref
FROM (
SELECT
users.firstname,
users.lastname,
users.email,
users.status,
users.active,
CONCAT(
users.preference_1, ',',
users.preference_2, ',',
users.preference_3
) AS pref
FROM users
) AS users
WHERE users.status = 1
AND users.active = 1
AND users.date = (
SELECT MAX(u.date) FROM users AS u WHERE u.email = users.email
)
LIMIT 10000

no need for subselect
add: ORDER BY users.date DESC LIMIT 1 this way you sort the list by date and return only the "1st elemet" which is the one with the "biggest/latest" date

Well, looks like you want to fetch the latest row for each user.
Here's a query that can do it. (It also uses subquery. I don't understand the necessity for using subquery to concat though)
SELECT DISTINCT us.email, us.preference FROM users AS us WHERE us.date = (
SELECT MAX(u.date) FROM users AS u WHERE u.email = us.email
)
This does not fetch all the details you want. But gives you the basic idea about the query you might have to run.

Related

SQL: Order by Messages doesn't work

why does this SQL Code not run?
user_chats
id | user_id | to_user_id | ad_id | timestamp
----------------+---------+------------+---------+-----------
1 | 1 | 6 | 13 | 1513516133
user_messages
id | chat_id | text | user_id | timestamp
----------------+---------+------------+---------+-----------
1 | 1 | Hello | 1 | 1513516133
2 | 1 | Hi! | 6 | 1513516754
I want to get the Chats and order them by user_messages.timestamp.
My SQL Code is:
SELECT user_chats.id,
user_chats.timestamp,
ad_id,
title,
user_chats.user_id
FROM user_chats
INNER JOIN ads
ON ads.id = ad_id
WHERE user_chats.user_id = "1"
OR user_chats.to_user_id = "1"
ORDER BY (SELECT id
FROM user_messages
WHERE chat_id = user_chats.id
ORDER BY user_messages.id DESC)
The issue is that you've used a subquery in your Order By clause: as this returns multiple results for each record in the main query it cannot be used to order the results of the main query.
I think you're trying to order the results by the latest message in each chat, but simply joining the user_messages table will mean you'll get duplicates (each chat being returned once per message). You can get around this by joining to an inline view:
SELECT DISTINCT user_chats.id,
user_chats.timestamp,
ad_id,
title,
user_chats.user_id
FROM user_chats
INNER JOIN ads
ON ads.id = ad_id
LEFT JOIN
--in line view aliased 'UM' returns one row per chat_id in user_messages, with the last timestamp for that ID
(SELECT max(timestamp) LastMessage,
chat_id
FROM user_messages
GROUP BY chat_id) um
ON um.chat_id = user_chats.id
WHERE user_chats.user_id = 1
OR user_chats.to_user_id = 1
ORDER BY um.LastMessage desc

mysql if there is a duplicate retrieve the most recent date of it

My previous post was confusing.
This is how my table data loks:
id | firstname | lastname | email | modified_date | preference_1 |pref..
1 | steven | smith | steven#gmail.com 2013-06-10 04:01:25 | Player | dot
2 | Bill | Johnson | bill#gmail.com | 2014-06-10 04:01:25 | code | pow
3 | steven | smith | steven#gmail.com | 2014-10-10 12:01:25 | pol | pl
I have 3 columns preference_1, preference_2 and preference_3
The reason why I do a subselect is concat them into one column.
The query below works fine, however, it returns duplicate email addresses.
If there is a duplicate it should return the latest modified_date
so it should return row number 2 and 3. It should not return row number 1 since the email address is the same as row number 3 but with an older modified date
SELECT
users.firstname,
users.lastname,
users.email,
users.pref
FROM (
SELECT
users.firstname,
users.lastname,
users.email,
users.status,
users.active,
CONCAT(
users.preference_1, ',',
users.preference_2, ',',
users.preference_3
) AS pref
FROM users
) AS users
WHERE users.status = 1
AND users.active = 1
GROUP BY users.id
LIMIT 10000
You can use a sub query to get the max modified date grouped by email address, and join that against users.
Something like this.
SELECT
users.firstname,
users.lastname,
users.email,
users.status,
users.active,
CONCAT(
users.preference_1, ',',
users.preference_2, ',',
users.preference_3
) AS pref
FROM users
INNER JOIN
(
SELECT email, MAX(modified_date) AS modified_date
FROM users
WHERE status = 1
AND active = 1
GROUP BY email
) sub0
ON users.email = sub0.email
AND users.modified_date = sub0.modified_date
WHERE users.status = 1
AND users.active = 1

Mysql - join 2 queries with limit

Im not very familiar with using 'join' in queries. I really tried solving this by my own, but it seems to be too hard.
I got 2 Tables:
Table 'users':
+-----------------+-----------------+
| member | online |
+-----------------+-----------------+
| mahran | 1 |
| peter | 1 |
| Jen | 1 |
| Steve | 0 |
+-----------------+-----------------+
Table 'tickets'
+-----------------+----------------+----------------+
| name | category | time |
+-----------------+----------------+----------------+
| mahran | silver | 1 |
| peter | blue | 1 |
| mahran | blue | 2 |
| peter | red | 3 |
| peter | green | 2 |
| Jen | silver | 1 |
+-----------------+----------------+----------------+
The chellange:
I need each member (users.member) who's online (users.online). The next thing is to get the category for each member (user.member = tickets.name) with the highest time (probably ORDER BY time DESC LIMIT 1).
So, for example:
Peter is online. Peters highest time is 3 at the position of category=red. So I want peter to show up in the result with his category 'red'. Mahran would show up with blue. Jen would get silver. And steve would be left out because he's not online.
I hope this was clear. In general I know how the queries would look like but theres no chance for me merging them together.
What needs to be merged:
SELECT member FROM users WHERE online = 1;
|
v for each member
SELECT category FROM tickets WHERE name=users.member ORDER BY time DESC.
So, any ideas how to solve this?
Here is a fiddle with a not working query: Click
You can do this easily with a correlated subquery:
select u.member,
(select t.category
from tickets t
where t.name = u.member
order by t.time desc
limit 1
) as MostRecentCategory
from users u
where u.online = 1;
This can make use of the following indexes: users(online, member) and ticket(member, time, category).
Here is the query you're looking for:
SELECT U.member
,T.category
FROM users U
INNER JOIN tickets T ON T.name = U.member
INNER JOIN (SELECT T2.name
,MAX(T2.time) AS [maxTime]
FROM tickets T2
GROUP BY T2.name) AS M ON M.name = T.name
AND M.maxTime = T.time
WHERE U.online = 1
The use of [name] to join the two tables is not a good practice, it's much better to use keys instead. But my query is just here to help you understanding the process of jointure.
Hope this will help you.
If i understand you correctly
SELECT DISTINCT users.member, tickets.category FROM tickets JOIN users ON users.member = tickets.name WHERE users.online = 1 ORDER BY tickets.time DESC
Can you make sql fiddle?
USE DISTINCT
stackoverflow.com/questions/11704012/mysql-distinct-join
try this
SELECT DISTINCT User.member,Ticket.category FROM users AS USER
INNER JOIN tickets AS Ticket ON (User.member = Ticket.name)
WHERE User.online = 1;
Sorry, but peter seems to be RED, It's time is 3. Don't you?
Depending on table definition, is not guaranteed to have one only result for each user.
For example, if peter has time 3 in two categories, you can get one different category depending of the SQL sorting method.
To be sure, tickets.Category and tickets.time must be in a unique key (both toghether, not a unike key for each field)
Assuming that, the Query could be this.
select t2.name, t2.category
from
tickets t2
INNER JOIN (Select
u.member, max(time)
from users u, tickets t
where
u.member = t.name
and u.online = 1
group by u.member
) as usermaxtime on t2.name = usermaxtime.member;

Combine SELECTing a record with COUNT

I have this MySQL query here which works GREAT! There is one extra thing I need to do though. Currently, it is returning the highest percentage back. The highest percentage is based on the amount of occurrences that a particular record type has been generated in the database on a particular date. What I want it to do is also return the name of the associated record that has this high percentage. I've tried incorporating it into the query below but it seems to be always failing. Any advice on this would be awesome.
SELECT *, COALESCE((acknowledged / generated), 0) AS result
FROM (
SELECT (
SELECT COUNT(*)
FROM logs
INNER JOIN generated_logs
ON generated_logs.log_fk = logs.log_pk
WHERE logs.department_fk = ?
AND DATE(generated_logs.generated_time) = ?
) AS generated, (
SELECT COUNT(generated_logs.log_fk) AS magnitude
FROM logs
INNER JOIN generated_logs
ON generated_logs.log_fk = logs.log_pk
WHERE logs.department_fk = ?
AND generated_logs.acknowledged = 1
AND DATE(generated_logs.generated_time) = ?
GROUP BY generated_logs.log_fk
ORDER BY magnitude DESC
LIMIT 1
) AS acknowledged ) AS result
Current output is:
+-----------+--------------+--------+
| Generated | Acknowledged | Result |
+-----------+--------------+--------+
| 6 | 3 | 0.50 |
+-----------+--------------+--------+
What I need is:
+-----------+--------------+--------+----------+
| Generated | Acknowledged | Result | Name |
+-----------+--------------+--------+----------+
| 6 | 3 | 0.50 | Test Log |
+-----------+--------------+--------+----------+
The name is a field in the logs table.
One more try ...
SELECT *, COALESCE((a.magnitude / g.generated), 0) AS result
FROM
(
SELECT COUNT(*) AS generated
FROM logs
INNER JOIN generated_logs
ON generated_logs.log_fk = logs.log_pk
WHERE logs.department_fk = ?
AND DATE(generated_logs.generated_time) = ?
) AS g,
(
SELECT COUNT(generated_logs.log_fk) AS magnitude, logs.name
FROM logs
INNER JOIN generated_logs
ON generated_logs.log_fk = logs.log_pk
WHERE logs.department_fk = ?
AND generated_logs.acknowledged = 1
AND DATE(generated_logs.generated_time) = ?
GROUP BY generated_logs.log_fk
ORDER BY magnitude DESC
LIMIT 1
) AS a

Show "0" in COUNT column when WHERE does not match?

What I would like to do is retrieve all data from a table, and order them by the number of games the user played in a specific category. Is there any way I can use some sort of "COUNT WHERE" sql statement?
here's what i have so far. it will only return the user if they have played a game in the "fps" category, but I want it to show all users in descending order even if they have not played an fps game. please excuse my crappy tables
SELECT user_data.user, COUNT(played_games.game_cat) as 'count'
FROM user_data, played_games
WHERE user_data.user_id = played_games.user_id and played_games.game_cat = 'fps'
GROUP BY user_data.user_id
ORDER BY 'count' DESC;
user_data table
user_id | user
1 | jeff
2 | herb
3 | dug
played_games table
id | user_id | game | game_cat
1 | 2 | kill | fps
2 | 1 | shoot| fps
3 | 2 | COD | fps
4 | 3 | dogs | cas
You need a LEFT OUTER JOIN to get the records even if a corresponding record does not exist in the other table.
SELECT user, coalesce(count(game_cat), 0) as count
FROM user_data LEFT OUTER JOIN played_games
ON user_data.user_id = played_games.user_id AND played_games.game_cat='fps'
GROUP BY user_data.user_id
ORDER BY count desc;
Gives the following result on my screen
+------+-------+
| user | count |
+------+-------+
| herb | 2 |
| jeff | 1 |
| dug | 0 |
+------+-------+
This is how I'd do it. No subquery, no COALESCE, no COUNTIF junk.
SELECT `users`.`user`, COUNT(`played_games`.id) AS `c`
FROM `users`
LEFT OUTER JOIN `played_games` ON
`users`.`user_id` = `played_games`.`user_id`
AND `played_games`.`game_cat` = "fps"
GROUP BY `users`.`user_id`
ORDER BY `c` DESC, `user` ASC
SQLFiddle (not sure if you can link them like this...)
Try this:
SELECT ud.user, coalesce(sum(pg.game_cat = 'fps'), 0) Total
FROM user_data ud
LEFT JOIN played_games pg ON ud.user_id = pg.user_id
GROUP BY ud.user_id
ORDER BY Total DESC
This will show all users and the amount of times they've played a game with category 'fps'.
The coalesce one is promising, but doesn't work for me, sigh~ I just found NULLIF is a good way to solve this problem. Remember to use LEFT JOIN
COUNT( NULLIF(TABLE.ATTR, 1) ) AS total_count
The TABLE.ATTR is some field that can be NULL, here is an example:
SELECT Posts.*, COUNT( NULLIF(Comments.user_email, 1) ) as comment_num
FROM (`Posts`)
LEFT OUTER JOIN `Comments` ON `Comments`.`post_id` = `Posts`.`id`
GROUP BY `Posts`.`id`
LIMIT 5
Got the idea from http://www.bennadel.com/blog/579-SQL-COUNT-NULLIF-Is-Totally-Awesome.htm
Below query the all game category with user id and order by count
select * from (SELECT user_data.user, COUNT(played_games.game_cat) as 'count'
FROM user_data, played_games
WHERE user_data.user_id = played_games.user_id(+) GROUP BY user_data.user_id)
order by count desc

Categories