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 :)
Related
Mysql table structure looks like this:
subject ca quiz exam exam_cumulative positionineachcourse matric_no name
Maths 10 20 34 64 HT/001 John
Econs 14 14 40 68 HT/002 Mark
History 20 30 60 110 HT/003 Grace
Chem 15 15 50 80 HT/004 Alice
Bio 12 13 60 85 HT/005 Larry
How can get the position of each student in each course and then get also their overall positions like 1ST, SND, 3RD, 4TH and 5TH?
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')
I have the following table:
id speed date
1 0 01/01/2015
2 0 01/01/2015
3 0 01/01/2015
4 0 01/01/2015
5 0 01/01/2015
6 0 01/01/2015
7 25 01/01/2015
8 78 01/01/2015
9 13 01/01/2015
10 45 01/01/2015
11 0 01/01/2015
12 80 01/01/2015
13 86 01/01/2015
14 10 01/01/2015
15 0 01/01/2015
16 0 01/01/2015
17 0 01/01/2015
18 0 01/01/2015
This is just a small part of the table, it has many dates. Each new date starts and ends with an unknown amount of zeros. And I have to skip these zeros and get only what's between them. So I came up with the following solution:
Get the ID of the first row whose speed is positive (in our table it's id number 4).
Get the ID of the last row whose speed is positive (in our table it's id number 12).
Get lines between these two IDs (4 and 12).
I get the id of the first row whose speed is positive:
$q1=$conn->prepare("SELECT * FROM tableX WHERE speed > 0 order by date asc LIMIT 1");
$q1->execute();
$r1=$q1->fetch();
$first_id = $r1['id'];
And then get the id of the last row whose speed is positive:
$q2=$conn->prepare("SELECT * FROM tableX WHERE speed > 0 order by date desc LIMIT 1");
$q2->execute();
$r2=$q2->fetch();
$last_id = $r2['id'];
And then use those ids to get what I want:
$q3=$conn->prepare("SELECT * FROM tableX WHERE id between '$first_id' and '$last_id'");
$q3->execute();
while($r3=$q3->fetch(){}
Expected result:
id speed date
7 25 01/01/2015
8 78 01/01/2015
9 13 01/01/2015
10 45 01/01/2015
11 0 01/01/2015
12 80 01/01/2015
13 86 01/01/2015
14 10 01/01/2015
PS: row 11 is not a bug.
My code is actually working but I think this solution of mine is lame, so I am looking for an improvement, kind of all these three queries in one!
I'm not sure if this is exactly what you want, but I think this will be equivalent to your whole code:
$q3=$conn->prepare("SELECT * FROM tableX WHERE speed > 0");
$q3->execute();
while($r3=$q3->fetch(){}
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;
I have tried about 10 different variations of queries similar to the following:
SELECT WEEKOFYEAR( dateline ) AS weekno, COUNT( 1 ) AS posts
FROM post
GROUP BY WEEKOFYEAR( dateline )
LIMIT 0 , 30
The resulting data is always a few results and about 600,000 "NULL" like so:
weekno posts
NULL 591843
1 57
2 42
3 25
4 44
5 9
6 38
7 15
8 41
9 10
10 130
11 77
12 69
13 36
14 25
15 25
16 24
17 44
18 42
19 14
20 49
21 70
22 41
23 40
24 57
25 40
26 31
Here is the table structure for dateline:
# Name Type Collation Attributes Null Default Extra
7 dateline int(10) UNSIGNED No 0
All of the rows have a value in dateline.
I need to get some sort of group by week working because ultimately I want to graph out the post activity with and without a specified forum section. I don't know why I'm getting all of these NULL results.
I think your date is stored in unixtime integer format, assuming that it is unixtime try FROM_UNIXTIME function
SELECT WEEKOFYEAR(FROM_UNIXTIME(dateline)) AS weekno, COUNT( 1 ) AS posts
FROM post
GROUP BY WEEKOFYEAR(FROM_UNIXTIME(dateline))
LIMIT 0 , 30
To return weeks from different year try this
SELECT
FROM_UNIXTIME(dateline, '%Y') Year,
WEEKOFYEAR(FROM_UNIXTIME(dateline)) AS weekno, COUNT( 1 ) AS posts
FROM post
GROUP BY FROM_UNIXTIME(dateline, '%Y'), WEEKOFYEAR(FROM_UNIXTIME(dateline))
LIMIT 0 , 30
DEMO HERE