Bunching a group of notifications - php

I have a notifications table with me:
+----+------+--------+--------+------------+
| ID | User | Object | Action | TimeStamp |
+----+------+--------+--------+------------+
| 1 | 1 | 3 | Like | 2014-05-01 |
| 2 | 2 | 3 | Like | 2014-05-01 |
| 3 | 3 | 3 | Like | 2014-05-01 |
| 4 | 3 | 5 | Share | 2014-05-01 |
+----+------+--------+--------+------------+
If you can see, the Users 1, 2, 3 have liked the same object 3. In the Notifications window, if we just give a simple SELECT query, it shows like this:
User 1 has liked Object 3. 2 mins ago
User 2 has liked Object 3. 2 mins ago
User 3 has liked Object 3. 2 mins ago
User 3 has shared Object 5. 2 mins ago
But since the action has been done on the same object, I would like to bunch or group the notifications like this:
Users 1, 2, 3 has liked Object 3. 2 mins ago
User 3 has shared Object 5. 2 mins ago
I have the following questions:
How do I group / bunch the notifications?
Is my notifications table schema the right one?

select object, action, group_concat(`user`) as users
from notifications
group by object, action

Related

how to alter table column in mysql and php?

i have 1 table in that i want to reorder the views column using alter function in my php file basically it should be reorder in most views to least views order.and want it to display in same order has altered but it is showing in order of id.
Now here i dont want to use ORDER BY views DESC thats why i am using alter function. because i am using ORDER BY name ASC already in my php file.
TABLE => users
id | name | views
1 | user1 | 700
2 | user3 | 900
3 | user1 | 200
4 | user4 | 900
5 | user4 | 800
6 | user4 | 800
7 | user3 | 900
8 | user4 | 900
9 | user5 | 100
10 | user5 | 100
// this is random table..//
ULtimately i am looking for that when by table is in views ORDERED then i will select data from table and if there are same name then it should be order in views as ALTERED so that i get ouptup like this :
id | name | views
1 | user1 | 900
2 | user1 | 700
3 | user1 | 200
4 | user3 | 900
5 | user4 | 900
6 | user4 | 800
7 | user5 | 900
8 | user5 | 900
9 | user5 | 300
10 | user5 | 100
SQL tables are unordered sets. They have no intrinsic order, and you should never rely on any order returned from queries that don't explicitly state an order by clause. In your case, it seems you need two elements in the ordering - first by name, and then by views:
SELECT *
FROM mytable
ORDER BY name ASC, views DESC

How to count all indentical values in Column which belongs to Different Values in another column

I have a mysql database table which has 4 columns: ID, Date, SessionID, UserID(irrelevant here). Let's call them A, B, C,
What I can't figure out is how to count how many sessions has been booked to specific date.
For example something like this
A | B | C
---|------------|------
1 | 2016-02-12 | 1 |
2 | 2016-02-12 | 1 |
3 | 2016-02-13 | 1 |
4 | 2016-02-12 | 5 |
5 | 2016-02-12 | 5 |
6 | 2016-02-13 | 2 |
7 | 2016-02-18 | 2 |
8 | 2016-02-19 | 3 |
So I want that my php code would output
that for date 2016-02-12 I have 2 entries with value 1 and 2 entries with value 5.
For date 2016-02-13 I have one entrie with value 1 and one with value 2.
This should work as you need
SELECT B AS date,COUNT(C) AS sessions FROM table GROUP BY B,C
It's a simple GROUP BY.
SELECT Date, SessionID, COUNT(*)
FROM yourTable
GROUP BY Date, SessionID

Query with each value only used once MySql

I've got a problem!
I've got a simple table which contains player_1, player_2, and played.
+---------+----------+----------+
| player1 | player2 | played |
+---------+----------+----------+
| 1 | 2 | 1 |
| 1 | 3 | 2 |
| 1 | 4 | 1 |
| 1 | 5 | 0 |
| 1 | 6 | 0 |
| 2 | 3 | 3 |
| 2 | 4 | 2 |
| 2 | 5 | 1 |
| 2 | 6 | 3 |
| 3 | 4 | 1 |
| 3 | 5 | 2 |
| 3 | 6 | 0 |
| 4 | 5 | 3 |
| 4 | 6 | 1 |
| 5 | 6 | 3 |
+---------+----------+----------+
and so on... There are 78 records, because there are 13 players in total.
I would like a result that shows me which 'matches' have been least played. So, e.g. a person was sick and couldn't play last time, the played games between that person and other players are lower. This game is more likely to be in the result.
But in each result, which shows me 6 matches (1 player has some time off), a player can be displayed only once! However, the least played games have to be in the result too. (well, the last part is easy, ORDER BY played ASC, LIMIT 6)...
How do I get each 13 players (well, without the one) to be in the result?
A nice result would be (well, now I'd like only 3 matches, because in this example are only 6 players)...
Every player plays a game in this round, and it is selected by ordening the least played games. The rest is just being filled in.
+---------+----------+----------+
| player1 | player2 | played |
+---------+----------+----------+
| 1 | 5 | 0 |
| 2 | 4 | 1 |
| 3 | 6 | 0 |
+---------+----------+----------+
You can think of this as a Graph Problem.
Let's say each player is a node, and every record in a table represents an arc, a weighted arc with weight of 'played', The number of games played between the 2 players connected with the arc.
Now, what you're looking for is an algorithm to find the 6 matches least played (if I understand correctly, the 6 matches to play in the next round) providing that every player plays only once a round.
I suggest using a greedy algorithm:
1. Sort arcs ascending.
2. While there are still arcs left.
2.1 Remove first arc and add to round_games.
2.2 Remove all arcs with any participating nodes in the previous arc.

PHP/MYSQL group and count by distinct dates and users

I'm trying to wrap my head around how to get a distinct count of days a user logged in, when the db has each login session stored with a time and date stamp (DATETIME column). EG:
USERID | TIME | BOUGHT
--------------------------
4 | 2012-07-16 04:44:52 | 3
4 | 2012-07-16 04:45:52 | 2
5 | 2012-07-16 04:54:52 | 5
4 | 2012-07-18 04:44:52 | 3
4 | 2012-07-18 04:45:52 | 2
4 | 2012-07-21 04:54:52 | 5
I want to search for how many times user 4 bought from the site - and the query should return 3 (because user 4 visited the site a total of 3 days). Do I have to use a PHP/MYSQL combination or can I do it in SQL?
SELECT USERID, COUNT(DISTINCT DATE(TIME)) FROM my_table GROUP BY USERID
See it on sqlfiddle.

Calculating total quantity of equipments for a date range

Project: I am working on a project which is about some rooms and equipments using in the rooms. The software is about scheduling the equipments in the rooms. In other words, it is a reservation software that reserves selected equipments in separate rooms for needed dates and times ranges. I have many tables in MYsSQL database working with Php but I will mention the tables my question is about. The tables I will relate my questions are equipment table (Table A), schedule table (Table B) and equipments using in the related schedule (Table C).
Table A: equipment list table
eqid | eqName | available|
1 | book | 90 |
2 | pen | 82 |
3 | computer | 25 |
In table A; eqid represents unique id of an equipment, eqName represents name of an equipment, available represents total available equipments existing.
Table B: schedule table
scheduleid | startDate | endDate | startTime | endTime | office |
1 | 2012-08-27 | 2012-08-27 | 08:30:00 | 10:00:00 | room1 |
2 | 2012-08-27 | 2012-08-27 | 09:30:00 | 11:00:00 | room3 |
3 | 2012-08-28 | 2012-08-30 | 08:30:00 | 12:00:00 | room2 |
4 | 2012-08-29 | 2012-08-31 | 11:30:00 | 14:00:00 | room1 |
5 | 2012-08-28 | 2012-08-28 | 10:30:00 | 14:00:00 | room3 |
6 | 2012-08-27 | 2012-08-30 | 08:30:00 | 10:00:00 | room4 |
7 | 2012-08-27 | 2012-08-27 | 10:30:00 | 12:00:00 | room4 |
8 | 2012-08-27 | 2012-08-30 | 08:30:00 | 11:00:00 | room6 |
9 | 2012-08-27 | 2012-08-27 | 10:30:00 | 12:00:00 | room5 |
In table B; scheduleid represents unique id for a schedule, startDate and endDate are date range for a schedule, startTime and endTime time range for a schedule, office means that where the schedule will take place. Let me give an example here. Scheduleid 1 means there is a reservation on 27th of august 2012, Monday and it is from 08.30 to 10:00. As it start and end on same day this is just one day reservation in room1. However, Scheduleid 3 means there is a reservation starts on 28th of august 2012, Tuesday and goes on until 30th of august 2012, Thursday at 08:30-12:00... in other words, it lasts for 3 days and everyday from 08:30 to 12:00... So there is a reservation from Tuesday to Thursday at 08:30 to 12:00 in room2... I hope this is clear.
Table C: equipments using in the related schedule
Autoid | scheduleid | eqid | amountInSch|
1 | 1 | 1 | 2 |
2 | 1 | 2 | 3 |
3 | 1 | 3 | 1 |
4 | 2 | 1 | 1 |
5 | 2 | 2 | 1 |
6 | 2 | 3 | 2 |
7 | 3 | 2 | 1 |
8 | 3 | 3 | 3 |
9 | 4 | 2 | 1 |
10 | 4 | 3 | 1 |
11 | 5 | 1 | 1 |
12 | 6 | 1 | 1 |
13 | 6 | 3 | 2 |
14 | 6 | 2 | 4 |
15 | 7 | 1 | 5 |
16 | 7 | 2 | 6 |
17 | 8 | 2 | 1 |
18 | 9 | 1 | 8 |
19 | 9 | 2 | 5 |
20 | 9 | 3 | 6 |
In table C: Autoid represents unique automatic id generated by auto-increment, scheduleid comes from Table B, eqid comes from Table A, amountInSch represents how many (amount) equipment will use in the related schedule. I want to give an example here. Scheduleid 1 in Table C, there are 3 rows. This means that scheduleid 1 related in TAble B will use 2 books (eqid 1), 3 pens (eqid 2) and 1 computer (eqid 3) in room1 specified dates and times in table B . Another example is that scheduleid 3 in Table C is related 2 rows. It means that 1 pen (eqId 2) and 3 computers (eqId 3) will be using in room2 from 27th to 30th of august 2012 everyday from 08:30 to 12:00.
The above is the explanation and give some information about the project. The table rows are not permanent. When you make a reservation, there will be a new row in Table B and if it is selected an equipment, there will be new rows in table C...
The Question:
I want to calculate left amount of a specific equipment when I supply eqId, startDate, endDate, startTime and endTime...
An example:
eqId: 1 (book)
startDate: 2012-08-27
endDate: 2012-08-27
startTime: 08:30:00
endTime: 12:00:00
Result should be: 14 books used in schedule and 76 left available books
Because: if you look scheduleIds and related eqIds, you will only see 1, 2, 6, 7, 9 scheduleIds related to my query(dates and eqId). If you sum the all amount of related in Table C, you will get the wrong result. In other words, related amounts for eqId(1-book) and for 1, 2, 6, 7, 9 scheduleIds are 2, 1, 1, 5, 8 respectively. So if you sum them you will get 17 which is wrong. Because, 1 and 9 schedule don't intersect each other in terms of start and end Times, and 6 and 7 don't intersect each other either. as a result of them 2 stays lonely and can be count separately. We must consider 1 and 9 as summed 8 because 8 is bigger than 2. it is same for 6 and 7, considered as 5 because of 5 is bigger than 1...
So folks! I am not sure how I can sum/ this in programming algorithm. Is there a way to do in SQL or do I have to use PHP and Mysql together? and How?
Cheers!
SQLFiddle Records
I started with the following SQL to gather all date ranges that intersect with the given range:
SELECT MAX(available) - IFNULL(SUM(amountInSch), 0)
FROM Table1
LEFT JOIN Table3 USING (eqid)
LEFT JOIN Table2 USING (scheduleid)
WHERE DATE(startDate) <= '2012-08-27' AND DATE(endDate) >= '2012-08-27'
AND endTime > '08:30' AND startTime < '12:00'
AND eqid = 1
Fiddle
This is only the first part. Next up you have to work out the possible overlaps; this wouldn't be practical to do with SQL, so I would suggest to do this in PHP.
The generic algorithm I would pick is unfortunately O(n**2), it goes like this:
create a timeline (demarcated by each day) with time as the horizontal axis
iterate over every date/time range and mark the time of its left and right edge to create time segments of every possible permutation.
using the segments, you sum vertically for overlaps and you take the daily maximum across.
Hope that helps.

Categories