MySQL Skip columns on condition - php

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(){}

Related

Laravel - Efficient Way to Query Monthly Data per Category

I'm working on a project that requires me to generate a report similar to this:
Category Total Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
-----------------------------------------------------------------------
Category 1 97 10 10 10 10 10 5 10 10 7 5 5 5
Category 2 120 10 10 10 10 10 10 20 10 5 5 10 10
Category 3 5 0 0 0 3 0 2 0 0 0 0 0 0
This report needs to be generated from data similar to this:
id category_id type year month amount
----------------------------------------------------------
1 1 16 2016 1 4
2 1 23 2016 1 6
3 1 76 2016 2 3
4 1 27 2016 2 3
5 1 18 2016 2 4
In the report, each month's number is simply the sum of the amount for that particular category, year, and month. I can do this just fine by querying the database for each month and for each category, but this type of approach doesn't scale very well if I need to generate a report with about a hundred categories because it would take over 1,200 queries (100 categories X 12 months)!
Any suggestions of how to make this more efficient?
Thanks!
The solution is grouping by two columns.I added the necessary code to format the results as you want.
Item::where('year', $year)
->groupBy('month', 'category_id')
->selectRaw('sum(amount) as sum, month, category_id')
->orderBy('category_id')
->orderBy('month')
->get()
->groupBy('category_id')
->map(function($item){
$item = $item->pluck('sum', 'month');
$item['total'] = $item->sum();
return $item;
});
Is this what you're looking for?
Category::where('year', 2016)
->select('month', 'year', DB::raw('SUM(amount) as amountTotal'))
->groupBy('month', 'year')
->get();

Mysql sum up the values of rows

SLNO UpazillaID CityArea VillageArea CharArea HillArea HaorArea TotalArea Year
6 1 11 44 11 11 11 11 2014
7 2 12 13 14 13 13 13 2013
I want to sum CityArea, VillageArea, CharArea, HillArea, HaorArea, TotalArea Where UpazillaID in 1,2.
Select (column1 + column2 + column3....) as totalcolumn. This will give you the sum per row.
SELECT (SUM(CityArea)+SUM(VillageArea)+SUM(CharArea)+SUM(CharArea)+SUM(CharArea)+SUM(TotalArea))
AS Total
FROM your_table
WHERE UpazillaID = 1

Count number of records per week giving massive number of NULL

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

CodeIgniter table class loops through db records 3 times - why?

This is my controller code (using Colin Williams' Template class):
$this->load->library('table');
$table['records'] = $this->db->get_where('data', array('category_1' => 'weight'));
$this->template->write_view('content', 'vw/weight_vw', $table, TRUE);
And my view code:
<div class="grid_16">
<?php echo $this->table->generate($records); ?>
</div>
Look at what I get
2 1 29 2011-01-01 10 weight
4 1 29 2010-11-03 11 weight
5 1 29 2011-05-02 10 weight
6 1 42 2011-07-11 23 weight // the database only has records up to here
2 1 29 2011-01-01 10 weight // from here on it's repeated twice
4 1 29 2010-11-03 11 weight
5 1 29 2011-05-02 10 weight
6 1 42 2011-07-11 23 weight
2 1 29 2011-01-01 10 weight
4 1 29 2010-11-03 11 weight
5 1 29 2011-05-02 10 weight
6 1 42 2011-07-11 23 weight
Any ideas why this is happening? None of my code is inside a loop or anything like that.
Use
$this->output->enable_profiler()
to see the db queries.
Take the query and run it against your db directly.
It's most likey you have a bad join in your database model.

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