Mysql Group Data By Time - php

Updated Question:
Here is the data
m_to m_from m_id m_time
5 5 1 1374769716
5 5 2 1374771178
5 5 3 1374771294
5 5 4 1374771396
5 5 5 1374771784
1 5 6 1374772120
1 5 7 1374773097
5 1 8 1374773579
5 1 9 1374774095
5 1 10 1374774148
1 5 11 1374777304
444 5 12 1374779752
5 444 13 1374780378
5 5 14 1374781374
5 5 15 1374832375
444 5 16 1374837258
5 444 17 1374837525
5 444 18 1374838801
444 5 19 1374838976
1 5 20 1374842736
5 5 21 1374842954
444 5 22 1374843389
5 5 23 1374843466
1 5 24 1374843853
1 5 25 1374848855
444 5 26 1374848889
5 5 27 1374848912
1 5 28 1374849001
5 5 29 1374849056
444 5 30 1374850406
First coulmn is "m_to" second is m_from and third is m_id and fourht is m_time
Now what I want is, I wanna group by m_from and order by m_time. ut new message which ever wwill be added should be on top and the next row should be on second......etc
I have used.
SELECT m_from,m_time FROM messages WHERE m_to='5' GROUP BY m_from ORDER BY m_time DESC
but is resuting in something like this
444
1
5
so, its not correctly sorting data..

If you're grouping by one(or more) column then you have to do something to all the non-grouped columns in order for your query to make sense.
You have to say what you want done with all the grouped values. Usually something like SUM(), AVG(), MIN(), MAX(), GROUP_CONCAT()
If you're grouping by m_from, then you won't be able to sort by m_time, as all the records for m_from will be grouped together, and for the non-grouped values you will get an arbitrary answer, since you didn't specify what to do with the group.
You probably want to use an aggregate function, such as MAX(m_time) to get the highest value for m_time, and then sort on that.
I'd suggest something like.
SELECT MAX(m_id),m_from, MAX(m_time) as latest FROM messages
WHERE m_to='XXX' OR m_from='XXX'
GROUP BY m_from
ORDER BY latest DESC;

This seems to be an issue stemming from the SELECT * and GROUP BY. MySQL allows this to happen, but it can cause some issues.
MySQL extends the use of GROUP BY so that the select list can refer to nonaggregated columns not named in the GROUP BY clause. This means that the preceding query is legal in MySQL. You can use this feature to get better performance by avoiding unnecessary column sorting and grouping. However, this is useful primarily when all values in each nonaggregated column not named in the GROUP BY are the same for each group. The server is free to choose any value from each group, so unless they are the same, the values chosen are indeterminate. Furthermore, the selection of values from each group cannot be influenced by adding an ORDER BY clause. Sorting of the result set occurs after values have been chosen, and ORDER BY does not affect which values within each group the server chooses.
As far as getting the data you want, I think this will work for you:
SELECT * FROM `messages` ORDER BY m_from ASC, m_time DESC
If you want it sorted by time first, just move m_from ASC to the end
EDIT
Given your updated question, this should limit the columns to what you want:
SELECT m_from, m_time FROM `messages` ORDER BY m_from ASC, m_time DESC

You can get the m_from that correspond to the last message to appear at the top of the list by doing something like this :
SELECT m_from, MAX(m_time) AS m_time
FROM messages
GROUP BY m_from
ORDER BY m_time DESC
but hard to say without knowing what is the output that you want...
EDIT :
Hope this one will work :
SELECT m_user, MAX(m_id) as m_id, MAX(m_time) AS m_time
FROM (
SELECT m_from AS m_user, MAX(m_id) as m_id, MAX(m_time) AS m_time
FROM messages
WHERE m_to = 5
GROUP BY m_from
UNION
SELECT m_to AS m_user, MAX(m_id) as m_id, MAX(m_time) AS m_time
FROM messages
WHERE m_from = 5
GROUP BY m_to
) AS result
GROUP BY m_user
ORDER BY m_time DESC

Related

SQL lottery query

I have a simple table of 7 columns
Week ¦ 1st ¦ 2nd ¦ 3rd ¦ 4th ¦ 5th ¦ 6th ¦
Each week, my father adds Saturdays UK lottery numbers to a simple PHP script that I created. He has early onset Alzheimers and tries to keep his brain active. Tonight he asked me a question about the database. He asked me if it was possible to see the 6 most popular numbers.
I tried to create a simple SQL query:
SELECT 1st, 2nd, 3rd, 4th, 5th, 6th, COUNT(*) AS 'foo' FROM `dad` GROUP BY 1st, 2nd, 3rd, 4th, 5th, 6th ORDER BY foo DESC
But the results weren't as I expected.
1st 2nd 3rd 4th 5th 6th foo
2 6 8 32 33 35 1
3 6 12 17 35 40 1
3 6 31 43 46 53 1
etc
What I hoped would happen would be for the table to merge into one column, and then count and have a simple result, something like:
Number Count
2 1
3 2
6 3
8 1
And then maybe put it in ascending order. I can then use that SQL query to create a simple table for him to show the most common numbers.
I'm thinking of doing a general SQL query
SELECT 1st FROM `dad`
Then creating an Array with the results, then adding
SELECT 2nd FROM `dad`
To the end of the Array and continuing for all 6 columns, then using PHP to count the numbers individually.
Is there a quicker way?
Your first effort should go into fixing your data model. Each number should be stored on a separate row rather than in a column, like:
week pos num
1 1 6
1 2 8
1 3 32
Then your query would be a simple aggregate query:
select num, count(*) no_picks from dad group by num order by no_picks desc
For your given table structure, you would need to unpivot the columns to rows. In MySQL, you can use union all for this:
select num, count(*) no_picks
from (
select `1st` num from dad
union all select `2nd` from dad
union all select `3rd` from dad
union all select `4th` from dad
union all select `5th` from dad
union all select `6th` from dad
) t
group by num
order by no_picks
You can do:
select
n, cnt
from (
select
n,
count(*) as cnt
from (
select `1st` as n from `dad` union all
select `2nd` from `dad` union all
select `3rd` from `dad` union all
select `4th` from `dad` union all
select `5th` from `dad` union all
select `6th` from `dad`
) x
group by n
) y
order by cnt desc
limit 6

How to count multiple columns with mysqli?

I am facing a problem I am not capable to solve on my own. There a several questions out that regarding counting but I did no see one where the counting is done like I would need it. In my table I have three slots that can be booked by a Person, represented by their ID, like this:
ID | Slot1 | Slot2 | Slot3
1 45 53
2 1 27 6
3 53
4 6 45
5 15 53
It is possible that slots are free but it is not possible that an ID blocks to slots.
Now I would like to count how often each ID used on of the three slots. The result would look like this for the table above:
ID Count
1 1
6 2
15 1
27 1
45 2
53 3
Is that possible with one mysql statement or do I need to GROUP BY for each slot and add the slots up later in my script?
If it is possible to do the counting in mysql over all three slots, would it also be possible to join the result with a second table that holds the names to the IDs?
You want a union all and aggregation:
select slot, count(*)
from ((select slot1 as slot from t
) union all
(select slot2 as slot from t
) union all
(select slot3 as slot from t
)
) s
where slot is not null
group by slot
You can use UNION :
SELECT s.SLOT_ID, COUNT(*)
FROM (
SELECT slot1 as slot_id FROM YourTable
UNION ALL
SELECT slot2 FROM YourTable
UNION ALL
SELECT slot3 FROM YourTable ) s
GROUP BY s.slot_id

select and get the most repeated occurrence on mysql

I have a table and i need to recover most repeated occurrence
in the example the occurrence repeats is kills:8
I not want to get the most value, i need get the most repeated value
id | member | kills
1 | - | 9
2 | - | 8
3 | - | 4
4 | - | 8
5 | - | 7
thank you
Group by kills, then order by count of the values in a descending manner, then limit to only one row.
SELECT
kills,
COUNT(id) AS kill_count
FROM table
GROUP BY kills
ORDER BY kill_count DESC
LIMIT 1
Try this query
SELECT kills, COUNT(id) FROM TABLE_NAME GROUP BY kills HAVING COUNT(id) > 1
Juz refer the link
SELECT kills,
count(kills)
FROM TEMP
GROUP BY kills
ORDER BY count(kills) DESC LIMIT 1;
My only idea is to run a while loop that counts each value in the kills column, tallies it and then runs if statements to get the highest tally. Hope this helps.

Advanced (My)SQL Query, is this possible?

let me explain the whole thing with an example:
| id | product | rating |
1 23 54
2 23 54
3 23 53
4 24 33
5 26 22
6 24 11
Lets say we have multiple ratings for each product and want to display the three top products. This would mean we can can user Inner-/left-/right- Join to get the products name from another table, order it by desc and set a limit of 3. But this would show us the same product three times with a rating of 54, 54 and 53.
Is it possible to avoid products with the same id in the result just with SQL?
So the dream output from one SQL query would be:
| id | product | rating |
1 23 54
4 24 33
5 26 22
In words: the top three unique products by rating (and of course only the row of the item with the highest rating -> id 1 or 2 for product 23 and not id 3).
Further more if there is only one product or two products with multiple ratings it should only transfer 1 or 2 results.
You can do this by taking the maximum rating for each product and choosing the top three:
select product, max(rating) as maxrating
from table t
group by product
order by maxrating desc
limit 3;
If you want the id for this rating, you can use the substring_index()/group_concat() trick:
select product, max(rating) as maxrating,
substring_index(group_concat(id order by rating desc), ',', 1) as id
from table t
group by product
order by maxrating desc
limit 3;
Alternatively, you can eschew the group by:
select t.*
from table t
where not exists (select 1
from table t2
where t2.product = t.product and
(t2.rating > t.rating or
t2.rating = t.rating and t2.id > t.id
)
)
order by t.rating desc
limit 3;
The complicated where clause is because multiple ratings can be the same.
EDIT:
The not exists version is getting the highest rating on the highest id for each row. The logic is simply saying: "Get me all rows from the products table where the product in the row has no other row with a higher rating/id combination". This is an awkward way for people to understand "Get the row with the maximum rating". But it turns out to be easier for the database to process. It is typically the most efficient method in MySQL and often the most efficient method in other databases as well, particularly with the right indexes defined.
Use a SELECT DISTINCT query. Check out details here: http://dev.mysql.com/doc/refman/5.6/en/select.html

How to Group by user_id and order by desc

Hello i am aware this is very basic but right now i am so confused i want to GROUP BY user_id ORDER BY id DESC LIMIT 4 (i have posted short example of table and my query)
My table looks like where id is auto increment i only save user_id i only want to take one user_id only once which is lastest entry in database ignore other.
Table
---------------------
id | user_id |
---------------------
13 | 25 |
12 | 36 |
11 | 25 |
10 | 42 |
9 | 95 |
8 | 25 |
7 | 95 |
---------------------
so on
I have tried this
SELECT * FROM `table` GROUP BY user_id ORDER BY `id` DESC LIMIT 4
I want it to output 25,36,42,95 i have also tried many experiments but nothing seems to be working.
Do i need timestamp or something to make it in group? or what query will work?
You are doing a partial GROUP BY which does not work the way you expect. Here is a query which produces the desired results:
SELECT MAX(id) AS MAXID, user_id
FROM `table`
GROUP BY user_id
ORDER BY MAXID DESC
LIMIT 4
The behavior is explained here:
MySQL extends the use of GROUP BY so that the select list can refer to
nonaggregated columns not named in the GROUP BY clause. [...] You can
use this feature to get better performance by avoiding unnecessary
column sorting and grouping. However, this is useful primarily when
all values in each nonaggregated column not named in the GROUP BY are
the same for each group. The server is free to choose any value from
each group, so unless they are the same, the values chosen are
indeterminate. Furthermore, the selection of values from each group
cannot be influenced by adding an ORDER BY clause. Sorting of the
result set occurs after values have been chosen, and ORDER BY does not
affect which values within each group the server chooses.
In your example you need to get result like 25,36,42,95, but sort by ID field.
If you will sort by it you will get different result.
You get a grouping in your query so you cannot use columns that not chosen in query (id is ommited there)
If you still need to order by id, i think that you need to add order by MAX('id') or MIN('id')
In your case i`ll make next query:
SELECT user_id FROM `table` GROUP BY user_id ORDER BY MAX(`id`) DESC LIMIT 4
Try this
SELECT MAX(id) as countid , `user_id` from `table`
GROUP BY `user_id`
ORDER BY countid DESC
LIMIT 20
In stead of grouping, you can use distinct, like below sql query.
SELECT distinct(user_id) FROM `table` ORDER BY `id` DESC LIMIT 4
SELECT * FROM (
SELECT 13 id, 25 UserID
UNION ALL
SELECT 12 id, 36 UserID
UNION ALL
SELECT 11 id, 25 UserID
UNION ALL
SELECT 10 id, 42 UserID
UNION ALL
SELECT 09 id, 95 UserID
UNION ALL
SELECT 08 id, 25 UserID
UNION ALL
SELECT 07 id, 95 UserID
) a
GROUP BY userid ORDER BY id DESC LIMIT 4

Categories