mysql --> yearly max value with infomation of record id - php

I want to get the yearly max values and the record id information for further joins with other tables.
Consider the following table:
tur_id Datum SZ Art VW StV TV NSP
189 23.06.2010 09:40:00 S 1 -37 -35 46
7 11.05.2012 08:40:00 S 1 -19,9 -21 45
140 02.07.2011 10:30:00 S 1 -25 -26 45
62 31.07.2013 31.07.2013 S 1 -16 -16 42
136 12.07.2011 11:20:00 S 1 -21,4 -23 41
181 04.08.2010 10:00:00 S 1 -30,1 -28 41
195 24.10.2009 09:40:00 S 1 -45 -47 41
90 22.10.2013 22.10.2013 S 1 -14,2 -16 40
11 16.06.2012 10:50:00 S 1 -17 -18 40
153 13.05.2011 09:25:00 S 1 -27,4 -29 40
1 23.07.2014 23.07.2014 S 1 -13,6 -14 39
56 15.06.2013 15.06.2013 S 1 -17,3 -18 39
45 26.10.2012 26.10.2012 S 1 -17,4 -18 39
.....
The following query returns the yearly max values without record id (in my case turid).
SELECT year(datum) rok, max(nsp) FROM turniere GROUP BY year(datum)
Result:
rok max(nsp)
2009 41
2010 46
2011 45
2012 45
2013 42
2014 39
How can I get the info of the turid or the datum value?

You are half-way there. Join the original data back in:
SELECT t.*
FROM turniere t JOIN
(SELECT year(datum) as rok, max(nsp) as maxnsp
FROM turniere
GROUP BY year(datum)
) tt
ON year(t.datum) = tt.rok and t.nsp = tt.maxnsp;

Related

How can I create a mysql select subquery this on laravel 5 query builder

I have this query below with a subquery.
How do I generate it in laravel 5 query builder?
The thing that is bothering me is the sub query that shares the column from the first query.
SELECT
DATE(review_headers.`created_at`) AS `date`,
COUNT(review_headers.id) AS reviews,
(
SELECT
(ROUND((SUM(IF(rd2.`param_value` >=9, 1,0))/COUNT(rh2.id))*100,2)) - (ROUND((SUM(IF(rd2.`param_value` <7, 1,0))/COUNT(rh2.id))*100,2))
FROM review_headers rh2
INNER JOIN review_details rd2 ON rd2.review_header_id = rh2.id
WHERE DATE(rh2.created_at) <= DATE(review_headers.`created_at`)
) AS cumulativeNPS
FROM review_headers
INNER JOIN review_details ON review_details.review_header_id = review_headers.id
GROUP BY DATE(review_headers.`created_at`)
ORDER BY DATE(review_headers.`created_at`)
The tables:
review_headers
id subject created_at
------ ----------------------- ---------------------
20 review 8 2016-03-31 15:50:57
21 review 9 2016-03-30 15:50:57
22 review 10 2016-01-14 15:50:57
23 review 16 2016-04-25 08:19:03
24 review 17 2016-04-25 08:19:03
25 review 18 2016-04-19 08:19:03
26 review 19 2016-04-18 08:19:03
27 review 20 2016-04-17 08:19:03
28 review 21 2016-04-07 08:19:03
29 review 22 2016-03-27 08:19:03
30 review 23 2016-03-25 08:19:03
31 review 24 2016-04-25 08:19:03
32 review 25 2016-04-25 08:19:03
33 review 26 2016-04-19 08:19:03
34 review 27 2016-04-18 08:19:03
35 review 28 2016-04-17 08:19:03
36 review 29 2016-03-27 08:19:03
37 review 30 2016-03-25 08:19:03
review_details
id review_header_id param_value
------ ---------------- -------------
97 21 7
103 22 4
109 23 8
115 24 5
121 25 6
127 26 8
133 27 9
139 28 9
145 29 5
151 30 9
157 31 3
163 32 8
169 33 10
175 34 4
181 35 7
187 36 4
193 37 7
Here You have complete code based on your query:
$subQuery = \DB::table('review_headers as rh2')
->select(\DB::raw('ROUND((SUM(IF(rd2.`param_value` >=9, 1,0))/COUNT(rh2.id))*100,2)) - (ROUND((SUM(IF(rd2.`param_value` <7, 1,0))/COUNT(rh2.id))*100,2)'))
->join('review_details as rd2'. 'rd2.review_header_id', '=', 'rh2.id')
->whereRaw('DATE(rh2.created_at) <= DATE(review_headers.`created_at`)');
$query = \DB::table('review_headers')
->select(
\DB::raw('DATE(review_headers.created_at) AS date'),
\DB::raw('COUNT(review_headers.id) AS reviews'),
\DB::raw('(' . $subQuery->toSql() . ') as cumulativeNPS')
)
->join('review_details', 'review_details.review_header_id', '=', 'review_headers.id')
->groupBy('review_headers.created_at')
->orderByRaw('DATE(review_headers.created_at)')
->mergeBindings($subQuery);
I tried this and it seems to work.
$data = ReviewHeader::select(
DB::raw('DATE(review_headers.`created_at`) AS dateTime'),
DB::raw('(SELECT
(ROUND((SUM(IF(rd2.`param_value` >=9, 1,0))/COUNT(rh2.id))*100,2)) - (ROUND((SUM(IF(rd2.`param_value` <7, 1,0))/COUNT(rh2.id))*100,2))
FROM review_headers rh2
INNER JOIN review_details rd2 ON rd2.review_header_id = rh2.id
WHERE DATE(rh2.created_at) <= DATE(review_headers.`created_at`)
) AS cumulativeNPS'),
DB::raw('COUNT(review_headers.id) AS review')
)
->join('review_details', 'review_details.review_header_id', '=', 'review_headers.id')
->groupBy(DB::raw('DATE(review_headers.`created_at`)'))
->orderBy('review_headers.created_at')

How to count data group by per 6 hours interval in every day in timestamp from database in PHP?

this is my query:
$sql = "SELECT DATE( pm_timestamp ) AS d, HOUR( pm_timestamp ) AS h,
COUNT( * ) AS c FROM pm_impr_tracker WHERE campaign_id = '$camp_id' GROUP BY h,d order by `pm_timestamp`";
this gives per hours data but i want per 6 hours.
my results:
d h c
2015-08-23 6 6
2015-08-23 7 11
2015-08-23 8 26
2015-08-23 9 57
2015-08-23 10 36
2015-08-23 11 19
2015-08-23 12 21
2015-08-23 13 18
2015-08-23 14 18
2015-08-23 15 17
2015-08-23 16 107
2015-08-23 17 55
2015-08-24 8 26
2015-08-24 9 57
2015-08-24 10 36
2015-08-24 11 19
2015-08-24 12 21
2015-08-24 13 18
2015-08-24 14 18
The code you posted groups the records by hour. If you need them grouped by intervals of 6 hours then all you have to do is to make h be the number of such a 6 hours group in the day. For example, h = 0 is the group of hours 0..5 (i.e. HOUR(pm_timestamp) between 0 and 5), h = 1 is for hours 6..11 and so on.
This can be easily achieved if you divide the hour by 6 and ignore the remainder. That's what the MySQL DIV operator does for a living.
The query is:
SELECT DATE(pm_timestamp) AS d,
HOUR(pm_timestamp) DIV 6 AS h,
COUNT(*) AS c
FROM pm_impr_tracker
WHERE campaign_id = '$camp_id'
GROUP BY h, d

My While Statement is not clearing mysqli_query on second run. Is this normal?

I am trying to create an un-ordered list of weekly dates. But these dates should only populated what is applicable. In my db i have entries with dates ranging from 10/17 - 11/5.
the idea is to get the first date available then search for it and create the 1st week
<li>date - date</li>
Then add a week and search for a date in that week and print the following week sequence, then add a week, etc...
Below is my code:
$fromDt_info = mysqli_query($con,"SELECT * FROM " . $rec_table . " WHERE `date`='".$from_dt."'" );
echo '<ul>';
while($row = mysqli_fetch_array($fromDt_info)){
echo $row['0'];
$to_dt = date('Y-m-d',strtotime($from_dt . '+ 6 Days'));
echo '<li>'.date('m/d/Y',strtotime($from_dt)).' - '.date('m/d/Y',strtotime($to_dt)).'</li>';
$from_dt = date('Y-m-d',strtotime($from_dt . '+ 7 Days'));
//empty array somehow? Prints as many emtries for first date only. But prints updated dates in sequance.
}
echo '</ul>';
This is the result i am getting:
44 10/17/2014 - 10/23/2014
45 10/24/2014 - 10/30/2014
46 10/31/2014 - 11/06/2014
47 11/07/2014 - 11/13/2014
48 11/14/2014 - 11/20/2014
you can see it's printing two extra lines that i don't have entries for.
When i added the echo $row['0']; to print the id, then i noted it's printing all of the entries for the first date, which is five entries on that first date, but the dates printed are squential not relating to the id entry.
Do i need to somehow empty the array at the end of the while statement?
This is the Data in my db:
id date
44 2014-10-17
45 2014-10-17
46 2014-10-17
47 2014-10-17
48 2014-10-17
51 2014-10-20
52 2014-10-20
53 2014-10-20
55 2014-10-20
56 2014-10-20
57 2014-10-20
58 2014-10-21
59 2014-10-21
60 2014-10-21
61 2014-10-21
62 2014-10-21
63 2014-10-21
64 2014-10-21
65 2014-10-22
66 2014-10-22
67 2014-10-22
68 2014-10-22
69 2014-10-23
70 2014-10-23
71 2014-10-23
72 2014-10-24
73 2014-10-24
278 2014-10-27
279 2014-10-27
280 2014-10-27
281 2014-10-27
282 2014-10-27
283 2014-10-27
284 2014-10-27
285 2014-10-28
286 2014-10-28
287 2014-10-28
288 2014-10-29
289 2014-10-29
290 2014-10-29
291 2014-10-29
293 2014-10-30
294 2014-10-30
295 2014-10-30
296 2014-10-30
297 2014-10-30
298 2014-10-30
299 2014-10-31
300 2014-10-31
301 2014-10-31
302 2014-10-31
303 2014-10-31
304 2014-10-31
305 2014-11-03
306 2014-11-03
307 2014-11-03
308 2014-11-03
309 2014-11-04
310 2014-11-04
311 2014-11-04
312 2014-11-04
313 2014-11-04
314 2014-11-05
315 2014-11-05
316 2014-11-05
317 2014-11-05
318 2014-11-05
319 2014-11-05
320 2014-11-05

MySQL/PHP to generate values by date range

I've been reading plenty about crosstab reports (Pivot Tables) in PHP and I've been trying to complete a report but I'm stuck.
I have a DB Table with report_date, employee_name, employee_id, leader_name, leader_id, employee_dept, stat1, stat2, stat3, stat4, stat5, stat6.
what I'm trying to do is to be able to query and return a sum and division of values based on the report_date range selected. So if I choose to query data between 10/01/2014 & 10/25/2014, I need it to sum and divide all the values found within that range.
This is my current SQL query.
Select
report_date,
employee_name,
employee_id,
leader_name,
leader_id,
employee_dept,
stat1,
stat2,
stat3,
stat4,
stat5,
stat6,
SUM(stat2)/SUM(stat1) AS `Result Name2`,
SUM(stat3)/SUM(stat1) AS `Result Name3`,
SUM(stat4)/SUM(stat1) AS `Result Name4`,
SUM(stat5)/SUM(stat1) AS `Result Name5`,
SUM(stat6)/SUM(stat1) AS `Result Name6`
FROM daily_records
GROUP BY report_date, employee_id
Might be too much to ask but how do I use this in PHP to query the totals from a selected report_date range?
Edited to add Sample data:
DB table data
report_date employee_id employee_name employee_dept STAT1 STAT2 STAT3 STAT4 STAT5 STAT6 leader_name leader_id
9/11/2014 1983122 emp_name1 ARK 17 7941 191 5 8137 2 Name 1001
9/11/2014 1983130 emp_name2 ARK 11 5067 516 3 5586 1 Name 1001
9/11/2014 1983138 emp_name3 ARK 3 184 16 4 204 1 Name 1001
9/11/2014 1983138 emp_name4 ARK 12 2576 7 6 2589 2 Name 1002
9/11/2014 1983138 emp_name5 ARK 21 9069 400 139 9608 1 Name 1002
9/11/2014 1983328 emp_name6 ARK 69 17929 1893 1096 20918 1 Name 1002
9/11/2014 1983349 emp_name7 ARK 12 2259 17 112 2388 2 Name 1002
9/11/2014 1983349 emp_name8 ARK 23 8194 880 211 9285 2 Name 1003
9/11/2014 1983829 emp_name9 ARK 81 16175 1431 311 17917 2 Name 1003
9/11/2014 1983888 emp_name10 ARK 7 1442 22 9 1473 1 Name 1003
9/12/2014 1983122 emp_name1 ARK 35 6823 774 22 7619 1 Name 1001
9/12/2014 1983642 emp_name2 ARK 80 18268 1439 135 19842 2 Name 1001
9/12/2014 1983643 emp_name3 ARK 55 20321 962 466 21749 1 Name 1001
9/12/2014 1983677 emp_name4 ARK 72 16379 1157 418 17954 2 Name 1002
9/12/2014 1983682 emp_name5 ARK 17 5017 419 425 5861 1 Name 1002
9/12/2014 1983978 emp_name6 ARK 48 9898 228 94 10220 1 Name 1002
(I tried to paste the table with a proper format but I couldn't)
Stats 2 to 6 should be divided by stat 1 to get a result for each field.
for example: stat2 / stat1 AS Result Name
Let me know if you need anything else.
Thanks in advance
First you should use DATE type for date. After append your query date condition like that;
Select
report_date,
employee_name,
employee_id,
leader_name,
leader_id,
employee_dept,
stat1,
stat2,
stat3,
stat4,
stat5,
stat6,
SUM(stat2)/SUM(stat1) AS `Result Name2`,
SUM(stat3)/SUM(stat1) AS `Result Name3`,
SUM(stat4)/SUM(stat1) AS `Result Name4`,
SUM(stat5)/SUM(stat1) AS `Result Name5`,
SUM(stat6)/SUM(stat1) AS `Result Name6`
FROM daily_records
WHERE report_date >= "2014-10-01"
OR report_date <= "2014-10-25"
GROUP BY employee_id`

Age range query in MySQL based on two age fields

I'm losing some hair over this. I found several online threads with a similar issue, but not exactly what I am running into, so I am still a bit jammed.
I am writing a very complex query (at least its complex for me :))
In my ages table, I have an age_start and age_end field.
For example:
age_start | age_end
------------------------
0 - 64
19 - 23
0 - 19
25 - 29
65 - 100
...
And what I am trying to achieve is a query which reads in between these ranges.
The best I have come up with so far is having these two fields set as array values, and in my MySQL query do something like:
Enter Age: [ 33 ]
Get ages data into an array. And then query like:
...WHERE $age >= $age_start AND age <= $age_end...
Would return:
age_start | age_end
------------------------
0 - 64
25 - 29
Does anyone have any ideas or suggestion or a better approach to this?
SELECT *
FROM ages
WHERE 32 BETWEEN age_start AND age_end
SELECT
CASE
WHEN age < 13 THEN 'Under 13'
WHEN age BETWEEN 13 and 15 THEN '13 - 15'
WHEN age BETWEEN 16 and 20 THEN '16 - 20'
WHEN age BETWEEN 21 and 25 THEN '21 - 25'
WHEN age BETWEEN 26 and 30 THEN '26 - 30'
WHEN age BETWEEN 31 and 35 THEN '31 - 35'
WHEN age BETWEEN 36 and 40 THEN '36 - 40'
WHEN age BETWEEN 41 and 45 THEN '41 - 45'
WHEN age BETWEEN 46 and 50 THEN '46 - 50'
WHEN age BETWEEN 51 and 55 THEN '51 - 55'
WHEN age BETWEEN 51 and 55 THEN '56 - 60'
WHEN age BETWEEN 51 and 55 THEN '61 - 65'
WHEN age BETWEEN 51 and 55 THEN '66 - 70'
WHEN age BETWEEN 51 and 55 THEN '71 - 75'
WHEN age BETWEEN 51 and 55 THEN '76 - 80'
WHEN age BETWEEN 51 and 55 THEN '81 - 85'
WHEN age BETWEEN 51 and 55 THEN '86 - 90'
WHEN age BETWEEN 51 and 55 THEN '91 - 95'
WHEN age BETWEEN 51 and 55 THEN '96 - 100'
WHEN age >= 100 THEN 'Over 100'
WHEN age IS NULL THEN 'Not Filled In (NULL)'
END as age_range,
COUNT(ids) AS age_count,group_concat(ids) as chart_ids
FROM (SELECT
TIMESTAMPDIFF(YEAR, `TABLE_FIELD_OF_DATE_OF_BIRTH`, CURDATE()) AS age, user_id as ids
FROM
jw_user
WHERE
is_active=1
AND
is_deleted = 0
) as derived
GROUP BY age_range
ORDER BY age_range
and the would be amazing :)

Categories