I have a Table call payments,
paymentid stuid stu_name fullamount pay_comp
1 1234 Jhon 2600 Feb
2 1212 Silva 1300 Jan
3 1234 Jhon 1300 March
4 1212 Silva 3900 April
5 3333 Perera 15600 Dec
Here a student can pay for the whole year,for several month or for a single month,Payments are done by 1300,
For a example if "Silva" paid 1300 for the first time he will be paying for Jan.
If he doing a another 1300 payment,Then it will be marked as for next month,Which is "Feb".If someone complete 15600 payment it will be saved as "Dec".
The problem is that when calculating Total Amount for the Jan it must consider that 1300 from Dec payment.
What i want is to calculate total Amount for each month.The problem is "Pay_Com" column is insert records as above.It can be for the whole year or for a single month.Is there any way around this.
I tried different methods,can i use sum of full amount divided by 1300 to calculate full amount for each month.Can anyone suggest me a soultion or a sql Function.
even tried IF and Sum with cases..
SELECT
CASE
WHEN round(sum(full_amount)/1300) = 1 THEN 1
ELSE 0
END AS 'Jan',
CASE
WHEN round(sum(full_amount)/1300) = 2 THEN 2
ELSE 0
END AS 'Feb',
CASE
WHEN round(sum(full_amount)/1300) = 3 THEN 3
ELSE 0
END AS 'March',
Can anyone suggest me a Solution.
Thanks In Advance.
I am Looking for a Something Like.
Month Full_PaymentsRecived
Jan 20000
Feb 3900
.... ....
Dec 2600
You know that every stuid is due 1300 every month, you can calculate how much has been paid by every stuid. From this you can apportion forwards from month one decrementing the paid amount as you go.
SELECT Y.MM,
SUM(Y.DUEAMT) PAYMENTSEXPECTED,
SUM(Y.PAID) PAYMENTSRECEIVED,
(SUM(Y.PAID) / SUM(Y.DUEAMT)) * 100 RATIO_PAID_DUE,
SUM(CASE WHEN Y.PAID > 0 THEN 1 ELSE 0 END) NUMBER_OF_PAYMENTS_RECEIVED,
SUM(CASE WHEN Y.PAID = 0 THEN 1 ELSE 0 END) NUMBER_OF_PAYMENTS_MISSED,
SUM(CASE WHEN Y.PAID < Y.DUEAMT AND Y.PAID > 0 THEN 1 ELSE 0 END) NUMBER_OF_UNDERPAYMENTS
FROM
(
SELECT X.STUID,X.MM,
X.DUEAMT,
#IF(X.STUID <> #P, #TOTALPAID:=(SELECT SUM(FULLAMOUNT) FROM T WHERE T.STUID = X.STUID),0) TOTALPAID,
IF(X.STUID <> #P, #FULLAMOUNT:=(SELECT SUM(FULLAMOUNT) FROM T WHERE T.STUID = X.STUID)
#- X.DUEAMT
,
#FULLAMOUNT:=#FULLAMOUNT - X.DUEAMT) EXHAUST,
CASE WHEN #FULLAMOUNT >= X.DUEAMT THEN X.DUEAMT
WHEN #FULLAMOUNT < 0 THEN 0
ELSE #FULLAMOUNT
END AS PAID,
#P:=X.STUID
FROM
(
SELECT DISTINCT T.STUID , 1300 AS DUEAMT, S.MM
FROM T,
(
SELECT 1 AS MM UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION
SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION
SELECT 9 UNION SELECT 10 UNION SELECT 11 UNION SELECT 12
) S
) X , (SELECT #TOTALPAID:=0,#FULLAMOUNT:=0,#P:=0) FA
ORDER BY X.STUID,X.MM
) Y
GROUP BY Y.MM
The sub query S generates a due amount for each month for each student
The Sub query X then works out and amount paid for each month for each student
The sub query Y then aggregates to get a result (I have added some addition analysis not required in your question).
So given
MariaDB [sandbox]> select * from t;
+-----------+-------+----------+------------+----------+
| paymentid | stuid | stu_name | fullamount | pay_comp |
+-----------+-------+----------+------------+----------+
| 1 | 1234 | Jhon | 2600 | Feb |
| 2 | 1212 | Silva | 1000 | Jan |
| 3 | 1234 | Jhon | 1300 | Mar |
| 4 | 1212 | Silva | 3900 | Apr |
| 5 | 3333 | Perera | 15600 | Dec |
+-----------+-------+----------+------------+----------+
5 rows in set (0.02 sec)
Result
MM | PAYMENTSEXPECTED | PAYMENTSRECEIVED | RATIO_PAID_DUE | NUMBER_OF_PAYMENTS_RECEIVED | NUMBER_OF_PAYMENTS_MISSED | NUMBER_OF_UNDERPAYMENTS |
+----+------------------+------------------+-------------------+-----------------------------+---------------------------+-------------------------+
| 1 | 3900 | 3900 | 100 | 3 | 0 | 0 |
| 2 | 3900 | 3900 | 100 | 3 | 0 | 0 |
| 3 | 3900 | 3900 | 100 | 3 | 0 | 0 |
| 4 | 3900 | 2300 | 58.97435897435898 | 2 | 1 | 1 |
| 5 | 3900 | 1300 | 33.33333333333333 | 1 | 2 | 0 |
| 6 | 3900 | 1300 | 33.33333333333333 | 1 | 2 | 0 |
| 7 | 3900 | 1300 | 33.33333333333333 | 1 | 2 | 0 |
| 8 | 3900 | 1300 | 33.33333333333333 | 1 | 2 | 0 |
| 9 | 3900 | 1300 | 33.33333333333333 | 1 | 2 | 0 |
| 10 | 3900 | 1300 | 33.33333333333333 | 1 | 2 | 0 |
| 11 | 3900 | 1300 | 33.33333333333333 | 1 | 2 | 0 |
| 12 | 3900 | 1300 | 33.33333333333333 | 1 | 2 | 0 |
+----+------------------+------------------+-------------------+-----------------------------+---------------------------+-------------------------+
12 rows in set (0.04 sec)
Related
I am trying to create a query that allows me to select the data like shown below
organizing by the role 45 and showing its win rate in order of DESC.
For example champ_1 = 45 and champ_2 = 36 but some time its can be champ_1 = 36 and champ_2 = 45. When like this how would i make the query so that is orders the win rate for champion 45 depending on if its champ1 or champ2 and then organizing it desc.
id Role Champ_1 Champ_2 Champ_1_winrate Champ_2_winrate
---|------------|------------|-----------|-----------------|---------------
1 | 1 | 45 | 17 | 0.54 | 0.46
2 | 1 | 67 | 45 | 0.52 | 0.48
5 | 1 | 45 | 27 | 0.59 | 0.41
3 | 1 | 45 | 35 | 0.29 | 0.71
4 | 1 | 45 | 23 | 0.094 | 0.916
6 | 1 | 80 | 45 | 0.38 | 0.62
7 | 1 | 45 | 47 | 0.544 | 0.456
8 | 1 | 32 | 45 | 0.78 | 0.22
It should show the data:
id Role Champ_1 Champ_2 winrate
---|------------|------------|-----------|-----------------|
6 | 1 | 80 | 45 | 0.62 |
5 | 1 | 45 | 27 | 0.59 |
7 | 1 | 45 | 47 | 0.544 |
1 | 1 | 45 | 17 | 0.54 |
2 | 1 | 67 | 45 | 0.48 |
3 | 1 | 45 | 35 | 0.29 |
8 | 1 | 32 | 45 | 0.22 |
4 | 1 | 45 | 23 | 0.094 |
I have tried the following code and its the closest I have came for over 3 hours now, so could someone help please.
SELECT *
FROM Bronze_Matchups a
WHERE (Champ_2 = 24 AND Role = 'JUNGLE')
OR (Champ_1 = 24 AND Role = 'JUNGLE')
ORDER BY Champ_2_winrate desc, Champ_1_winrate asc
You can use UNION and ORDER BY (add desc or asc in ORDER BY clause as you need)
SELECT a.id, a.Role, a.Champ_1, a.Champ_2, a.Champ_2_winrate as winrate
FROM Bronze_Matchups a
WHERE a.Champ_2 = 24
AND a.Role = 'JUNGLE'
UNION
SELECT a.id, a.Role, a.Champ_1, a.Champ_2, a.Champ_1_winrate as winrate
FROM Bronze_Matchups a
WHERE a.Champ_1 = 24
AND a.Role = 'JUNGLE'
ORDER BY winrate
Use a case-statement in your order-by
SELECT *
FROM Bronze_Matchups a
WHERE
(Champ_2 = 24 AND Role = 'JUNGLE')
OR (Champ_1 = 24 AND Role = 'JUNGLE')
ORDER BY
CASE
WHEN Champ_2 = 24 THEN Champ_2_winrate
ELSE Champ_1_winrate
END
Currently I am developing a system to support a competition. In this competition there are 11 judges that give a grade to the participant. This grade is stored in a table per judge. With the following Select statement I retrieve the total score from the MySQL database (and also some inner joins to select other information from other tables).
Now I want to have ranking in this system, where also ex aequo is taken into account. I have tried several mysql solutions from this forum. But somehow the statement is always incorrect. Hopefully, someone can help me.
SELECT optreden.id, optreden.wedstrijd, optreden.jaartal,
liedje.titel, club.volledige_clubnaam,
(SELECT SUM(score.score_lied) FROM score WHERE score.optreden=optreden.id) AS score
FROM optreden
INNER JOIN liedje ON optreden.liedje=liedje.id
INNER JOIN club ON liedje.uitvoerende_club=club.id
WHERE optreden.wedstrijd="voorselectie" AND optreden.jaartal=2014
GROUP BY optreden.id
ORDER BY score_lied DESC
With this query, I get the following result:
+----+--------------+------+----------+--------------+------+
| id | Competition | Year | Title | Artist (club)| Score|
+----+--------------+------+----------+--------------+------+
| 12 | voorselectie | 2014 | Song 1 | Club 1 | 792 |
| 16 | voorselectie | 2014 | Song 2 | Club 2 | 600 |
| 10 | voorselectie | 2014 | Song 3 | Club 3 | 600 |
| 11 | voorselectie | 2014 | Song 3 | Club 3 | 500 |
| 12 | voorselectie | 2014 | Song 3 | Club 3 | 400 |
The query fetches information from the following tables:
Score: in this table the scores given by the 11 judges is stored as
line-items (result is given below);
Optreden: in this table the information from the club and the song is linked;
Club: information from the club,
such as name;
Liedje: information about the song, performed by the
club.
All the tables are linked by id's. In the result, there should come a column, with the ranking of the club.
The result from the table score is as follows:
+----+----+--------+----+
| ID | Pid| Userid | 85 |
+----+----+--------+----+
| 1 | 12 | 444 | 85 |
| 12 | 12 | 454 | 92 |
| 13 | 12 | 445 | 87 |
| 14 | 12 | 446 | 56 |
| 15 | 12 | 447 | 81 |
| 16 | 12 | 448 | 78 |
| 17 | 12 | 449 | 55 |
| 18 | 12 | 450 | 69 |
| 19 | 12 | 451 | 88 |
| 20 | 12 | 452 | 69 |
| 21 | 12 | 453 | 32 |
+----+----+--------+----+
Where the columns represent the following:
- ID: the id of the score in the table;
- Pid: the id of the performance (with this performing club and song are linked);
- Userid: the userid of the 11 judges;
- Score: the score given by each judge.
The end result should be as follows:
+----+--------------+------+----------+--------------+------+------+
| id | Competition | Year | Title | Artist (club)| Score| Rank |
+----+--------------+------+----------+--------------+------+------+
| 12 | voorselectie | 2014 | Song 1 | Club 1 | 792 | 1 |
| 16 | voorselectie | 2014 | Song 2 | Club 2 | 600 | 2 |
| 10 | voorselectie | 2014 | Song 3 | Club 3 | 600 | 2 |
| 11 | voorselectie | 2014 | Song 3 | Club 3 | 500 | 4 |
| 12 | voorselectie | 2014 | Song 3 | Club 3 | 400 | 5 |
I have tried the solution from Neville before and now again. I have rewritten the SQL statement as follows:
SELECT optreden.id, optreden.wedstrijd, optreden.jaartal,
liedje.titel, club.volledige_clubnaam,
(SELECT SUM(score.score_lied) FROM score WHERE score.optreden=optreden.id) AS score, CASE
WHEN #prev_value = score THEN #rank_count
WHEN #prev_value := score THEN #rank_count := #rank_count + 1
END AS rank,
FROM optreden
INNER JOIN liedje ON optreden.liedje=liedje.id
INNER JOIN club ON liedje.uitvoerende_club=club.id
WHERE optreden.wedstrijd="voorselectie" AND optreden.jaartal=2014
GROUP BY optreden.id
ORDER BY score_lied DESC
Here I get the error: Unknown column 'score' in 'field list'..
It seems that you are getting this error simply because there is no field score... I have extracted your inner SELECT into a JOIN so the real field can be used directly. (Not tested though, sorry)
SELECT optreden.id, optreden.wedstrijd, optreden.jaartal,
liedje.titel, club.volledige_clubnaam,
SUM(score.score_lied) AS score, CASE
WHEN #prev_value = SUM(score.score_lied) THEN #rank_count
WHEN #prev_value := SUM(score.score_lied) THEN #rank_count := #rank_count + 1
END AS rank,
FROM optreden
INNER JOIN liedje ON optreden.liedje=liedje.id
INNER JOIN club ON liedje.uitvoerende_club=club.id
LEFT JOIN score ON score.optreden=optreden.id
WHERE optreden.wedstrijd="voorselectie" AND optreden.jaartal=2014
GROUP BY optreden.id
ORDER BY score_lied DESC
Please note that you might face another little problem with this kind of ranking: Normally, when two entities end up on the same rank, the next rank is not given to the next person. Here's what I mean with an example, with two persons ranking in 3:
1, 2, 3, 3, 5
But in your code, it will give:
1, 2, 3, 3, 4
I hope this helps.
I have tried several things. However, I had forgotten to tell you one important feature I was gonna use. The ranking of the clubs should be presented through a presentation on a big screen. Therefor the MySQL code changed a little.
I have added a support table to my database. In this support table the sum of the scores is recorded with a INSERT INTO...SELECT statement.
When this insert is done. An update script is launched which makes the ranking in the table and also makes a correct calculation for ex aequo.
Here's the update statement:
SET #rank=0, #last_score = null, #tie_build_up = 0;
UPDATE ranking_voorselectie_lied
SET rank= #rank:= if(#last_score = totaal_score_lied, #rank, #rank+#tie_build_up+1),
tie_build_up= #tie_build_up:= if(#last_score = totaal_score_lied, #tie_build_up+1, 0),
last_score= #last_score:= totaal_score_lied
WHERE wedstrijd="voorselectie" AND jaar=2014
ORDER BY totaal_score_lied DESC;
This gives me the following result:
+--------------+------+----------+-------------------+------+-----+------------+
| Wedstrijd | Jaar | Optreden | totaal_score_lied | Rank | Tie | last_score |
+--------------+------+----------+-------------------+------+-----+------------+
| voorselectie | 2014 | 12 | 792 | 1 | 0 | 792 |
| voorselectie | 2014 | 16 | 82 | 2 | 0 | 82 |
| voorselectie | 2014 | 10 | 73 | 3 | 0 | 73 |
| voorselectie | 2014 | 15 | 51 | 4 | 0 | 51 |
| voorselectie | 2014 | 3 | 50 | 5 | 0 | 50 |
| voorselectie | 2014 | 11 | 42 | 6 | 0 | 42 |
| voorselectie | 2014 | 13 | 38 | 7 | 0 | 38 |
| voorselectie | 2014 | 8 | 38 | 7 | 1 | 38 |
| voorselectie | 2014 | 14 | 37 | 9 | 0 | 37 |
| voorselectie | 2014 | 5 | 35 | 10 | 0 | 35 |
| voorselectie | 2014 | 4 | 33 | 11 | 0 | 33 |
| voorselectie | 2014 | 7 | 25 | 12 | 0 | 25 |
| voorselectie | 2014 | 9 | 23 | 13 | 0 | 23 |
+--------------+------+----------+-------------------+------+-----+------------+
This is a simplification table structure that i have.
I have two tables.
TABLE 1
ID PTS PID TID
----------------------------------------
1 3 1 22
2 10 1 22
3 5 1 22
4 1 2 58
5 0 2 58
7 0 3 47
8 5 3 47
15 5 4 51
15 3 4 51
9 7 3 6
10 0 1 8
11 2 1 8
12 4 5 1
13 1 6 9
14 2 5 12
15 5 4 61
15 6 4 61
15 2 4 61
16 0 7 100
ect. ect. ect. ect.
TABLE 2
NAME PID
-------------------
Jhon 1
Peter 2
Lisa 3
Doe 4
Joey 5
Mike 6
Debby 7
ect. ect.
Now i need to select the latest two PTS from each TID and match them whit PID row on table 2. and calculate the Average.
THE DESIRED OUTCOME
NAME AVG
-------------------
Jhon 4,25
Peter 1,00
Lisa 6,00
Doe 4,00
Joey 3,00
Mike 1,00
Debby 0,00
ect. ect.
Clarification: the PID row are relational. Multiple TIDs can have the same PID and TIDs can have multiple PTS. I am using PDO socket.
At the time my query is:
$query = $db->prepare("SELECT IFNULL(AVG(pts), 0) AS P, TA1.PID AS TA1PID, name AS N FROM ".
"table1 TA1 LEFT JOIN table2 TA2 ON TA1.PID = TA2.PID ".
"GROUP BY name, TA2.PID ".
"ORDER BY TA1.id DESC");
But this calculates all the points(PTS) from TID. but i would like to only calculate the Two latest points(PTS) per TID. I have tried different queries the whole day but i cant figure it out. I am pretty new to SQL I managed to get one example working but with pure PHP and its not pretty :D
sqlFiddle: LINK
The problem is that it calculates all the TID points in Average. It only should calculate the two last entries per TID
I hope this is a clear question. I have tried my best to explain my problem. If any questions please ask. I have read other similar problems than mine here on Stackoverflow but i could not modify them to work for me.
You can select only the most recent 2 rows from the first table using this query
select t1.id, t1.pts, t1.pid, t1.tid
from table1 t1
join table1 t2 on t2.id >= t1.id and t1.tid = t2.tid
group by t1.id
having count(*) <= 2
and plug it into your original query instead of table 1
SELECT IFNULL(AVG(pts), 0) AS AVG, TA1.PID AS
Table1_ID, name AS Name FROM
(
select t1.id, t1.pts, t1.pid, t1.tid
from table1 t1
join table1 t2 on t2.id >= t1.id and t1.tid = t2.tid
group by t1.id
having count(*) <= 2
)
TA1 LEFT JOIN table2 TA2 ON TA1.PID = TA2.PID
GROUP BY name, TA2.PID
ORDER BY TA1.id DESC
Group Per N are pretty easy in Most DBs. Just use ROW_NUMBER. Unfortunately MySQL doesn't have them so we must simulate it
SELECT name,
Avg(PTS)
FROM
(
SELECT *,
CASE
WHEN #previousPID IS NULL
OR #previousTID IS NULL
OR ( #previousPID = ORDERED.pid
AND #previousTID = ORDERED.tid )
THEN #rownum := #rownum + 1
ELSE #rownum := 1
end rn,
#previousPID := ORDERED.pid ,
#previousTID := ORDERED.tid
FROM (SELECT t2.name,
t2.pid,
t1.id,
t1.tid ,
t1.Pts
FROM table2 t2
INNER JOIN table1 t1
ON T2.pid = t1.pid
ORDER BY t1.pid,
t1.tid,
t1.id DESC)ORDERED,
(SELECT #rownum := 0,
#previousPID := NULL,
#previousTID := NULL) t) CTE
WHERE CTE.rn <= 2
GROUP BY name
Which has the following Results
| NAME | AVG(PTS) |
|-----------|----------|
| Doe | 4 |
| Jhon | 4.25 |
| Joey | 3 |
| Lisa | 4 |
| Mike | 1 |
| No points | 0 |
| Peter | 0.5 |
DEMO
Looking at the intermediate results may help to understand how the CASE statements generate the rownumbers
| NAME | PID | ID | TID | PTS | #ROWNUM := 0 | #PREVIOUSPID := NULL | #PREVIOUSTID := NULL | RN | #PREVIOUSPID := ORDERED.PID | #PREVIOUSTID := ORDERED.TID |
|-----------|-----|----|-----|-----|--------------|----------------------|----------------------|----|-----------------------------|-----------------------------|
| Jhon | 1 | 3 | 22 | 5 | 0 | (null) | (null) | 1 | 1 | 22 |
| Jhon | 1 | 2 | 22 | 10 | 0 | (null) | (null) | 2 | 1 | 22 |
| Jhon | 1 | 1 | 22 | 3 | 0 | (null) | (null) | 3 | 1 | 22 |
| Jhon | 1 | 12 | 8 | 2 | 0 | (null) | (null) | 1 | 1 | 8 |
| Jhon | 1 | 11 | 8 | 0 | 0 | (null) | (null) | 2 | 1 | 8 |
| Peter | 2 | 5 | 58 | 0 | 0 | (null) | (null) | 1 | 2 | 58 |
| Peter | 2 | 4 | 58 | 1 | 0 | (null) | (null) | 2 | 2 | 58 |
| Lisa | 3 | 7 | 47 | 5 | 0 | (null) | (null) | 1 | 3 | 47 |
| Lisa | 3 | 6 | 47 | 0 | 0 | (null) | (null) | 2 | 3 | 47 |
| Lisa | 3 | 10 | 6 | 7 | 0 | (null) | (null) | 1 | 3 | 6 |
| Doe | 4 | 9 | 51 | 3 | 0 | (null) | (null) | 1 | 4 | 51 |
| Doe | 4 | 8 | 51 | 5 | 0 | (null) | (null) | 2 | 4 | 51 |
| Doe | 4 | 19 | 61 | 2 | 0 | (null) | (null) | 1 | 4 | 61 |
| Doe | 4 | 17 | 61 | 6 | 0 | (null) | (null) | 2 | 4 | 61 |
| Doe | 4 | 16 | 61 | 5 | 0 | (null) | (null) | 3 | 4 | 61 |
| Joey | 5 | 13 | 1 | 4 | 0 | (null) | (null) | 1 | 5 | 1 |
| Joey | 5 | 15 | 12 | 2 | 0 | (null) | (null) | 1 | 5 | 12 |
| Mike | 6 | 14 | 9 | 1 | 0 | (null) | (null) | 1 | 6 | 9 |
| No points | 7 | 18 | 100 | 0 | 0 | (null) | (null) | 1 | 7 | 100 |
I have the following structure to store clicks from a website on a Mysql database:
select * from contenido_clicks;
+-------------+-------------+------------+
| idContenido | fecha_click | servicetag |
+-------------+-------------+------------+
| 5 | 1392829606 | HJCS302 |
| 8 | 1392832379 | HJCS302 |
| 5 | 1392832433 | HJCS302 |
| 5 | 1392832435 | HJCS302 |
| 5 | 1392832437 | HJCS302 |
And so on...
Here I have lots on entries from different days and hours, and I need to get all of them and place on a 24 hours graph, to show the hours in the day that people makes more clicks. I can get the clicks per hour with:
SELECT cc.fecha_click div 3600 as Horas, COUNT(cc.idContenido) as Clicks
FROM contenido_clicks cc
GROUP BY fecha_click div 3600 ASC
But I dont know how to merge them in a 24 hour table.
Any ideas?
Create a Horas domain table with 24 rows and left join your contenido_clicks table with it
create table Horas
(
Hora integer not null
)
Insert into Horas (Hora) vlaues (0)
Insert into Horas (Hora) vlaues (1)
.
.
.
Insert into Horas (Hora) vlaues (23)
select *
from Horas h
left join (
SELECT cc.fecha_click div 3600 as Horas, COUNT(cc.idContenido) as Clicks
FROM contenido_clicks cc
GROUP BY fecha_click div 3600
) as hh on hh.Hora = h.Hora
order by h.Hora
I think you want to do some thing like this
SELECT *
FROM contenido_clicks
WHERE DATE_ADD(NOW(), INTERVAL 24 HOUR) > fecha_click
I think this will solve your problem
Thanks to the solution provided by jean, I write the following query:
SELECT h.hora, COUNT(cc.idContenido) as Clicks
FROM horas h
LEFT JOIN contenido_clicks cc ON h.hora = DATE_FORMAT(FROM_UNIXTIME(cc.fecha_click), '%H')
GROUP BY h.hora;
And get the following result:
+------+--------+
| hora | Clicks |
+------+--------+
| 0 | 0 |
| 1 | 0 |
| 2 | 0 |
| 3 | 0 |
| 4 | 0 |
| 5 | 0 |
| 6 | 0 |
| 7 | 0 |
| 8 | 0 |
| 9 | 5 |
| 10 | 3 |
| 11 | 7 |
| 12 | 4 |
| 13 | 3 |
| 14 | 0 |
| 15 | 5 |
| 16 | 1 |
| 17 | 5 |
| 18 | 8 |
| 19 | 0 |
| 20 | 0 |
| 21 | 1 |
| 22 | 0 |
| 23 | 0 |
+------+--------+
24 rows in set (0.00 sec)
Which are the correct results.
I have a table in mysql that has time date and in military format ( 2014-01-22 16:10:02 )
caller_data
|ID | caller_id | call_time
| 1 | 123 | 2014-01-22 16:10:02
| 2 | 123 | 2014-01-22 16:30:02
| 3 | 123 | 2014-01-22 17:10:02
| 4 | 123 | 2014-01-22 18:05:45
on the range of their time like 16:10 and 16:30 . I group them using HOUR(), the result is 16. I will count it of how many times did the caller call on the range of that hour. so that would be 2.
My query:
SELECT caller_id,
HOUR(str_to_date(date_stamp, "%Y-%m-%d %H:%i:%s")) as hourly,
count(*) as total
from caller_data
group by hourly
order by hourly;
which the result should be:
caller_id | hourly | total
123 | 16 | 2
123 | 17 | 1
123 | 18 | 1
I want to display these 3 rows on a 0-23 . I've been trying to display this with php but it display 3 times when I created a for $i <= 23 ..
for($i=0;i<=23;$i++)
{
foreach ($rec as $row):
echo $row['hourly'];
echo $row['caller_id'];
echo $row['total'];
endforeach;
}
I dont know if it's possible to display this on mysql.. can someone show how to do it with php or mysql?
| hours | caller_id | total
| 0 | 123 | 0
| 1 | 123 | 0
| 2 | 123 | 0
| 3 | 123 | 0
| 4 | 123 | 0
| 5 | 123 | 0
| 6 | 123 | 0
| 7 | 123 | 0
| 8 | 123 | 0
| 9 | 123 | 0
| 10 | 123 | 0
| 11 | 123 | 0
| 12 | 123 | 0
| 13 | 123 | 0
| 14 | 123 | 0
| 15 | 123 | 0
| 16 | 123 | 2
| 17 | 123 | 1
| 18 | 123 | 1
| 19 | 123 | 0
| 20 | 123 | 0
| 21 | 123 | 0
| 22 | 123 | 0
| 23 | 123 | 0
You can do this in SQL with a left outer join. You just have to type in all the hours:
select caller_id, n.n as hourly, coalesce(total, 0) as total
from (select 1 as n union all select 2 union all select 3 union all select 4 union all
select 5 union all select 6 union all select 7 union all select 8 union all
select 9 union all select 10 union all select 11 union all select 12 union all
select 13 union all select 14 union all select 15 union all select 16 union all
select 17 union all select 18 union all select 19 union all select 20 union all
select 21 union all select 22 union all select 23 union all select 24
) n left outer join
(select caller_id, HOUR(str_to_date(date_stamp, "%Y-%m-%d %H:%i:%s")) as hourly,
count(*) as total
from caller_data
group by hourly
) rep
on n.n = rep.hourly
order by hourly;