Selective print of MySQL results for multi-line chart - php

I need to make a googlechart print 4 lines that will represent the evolution of temperature of 4 sensors that store their readings in MySQL db.
My schema is:
id | datetime | node_id | temperature
if I run the query:
SELECT * FROM sensor_readings ORDER BY id DESC LIMIT 4
the result is like:
4 | 21-5-2014 17:00 | 3 | 18.6
3 | 21-5-2014 17:01 | 1 | 18.5
2 | 21-5-2014 17:02 | 4 | 18.7
1 | 21-5-2014 17:04 | 2 | 18.2
For on node I could just query the results - WHERE node_id = 1
Now for four nodes how can I make my query in order to be able to echo a code like
[date, temperature (of node1), node1, temperature (of node2), node2
....]
So that google chart is able to print my graph? I've made several attempts to load results in temporary arrays in php, without luck. Any idea how I could approach this issue?
Thanks a lot!

try with adding group by
SELECT * FROM sensor_readings ORDER BY id DESC GROUP BY datetime;
after that, you can use ajax to collect the result of the query as response.
then put the response into a or or what you want

Related

SQL QUERY how to select column by other constraints

I am using backpack-crud controller for
PHP-Laravel.
With the crudController given by backpack (library), all I have to do
is to query it with Laravel Eloquent (also raw sql is possible) queries.
Than the Backpack library will automatically
print the listview for me.
But I am struggling with this difficult query.
The thing is that I have 4 columns,
session_id | column_id | batch | data
10 | 1 | 1 | data1
10 | 2 | 1 | data2
10 | 1 | 2 | data1*
10 | 2 | 2 | data2*
Let's say this is the data I have.
I want to display this grouping by session_id, batch,
and ordering within row by column_id.
so the result query would be something like
1 : data1 data2
2 : data1* data2*
If there is a third batch with data
session_id | column_id | batch | data
10 | 1 | 3 | data1**
Then it would appear under the third batch as
3 : data1**
I can do this with code but not with sql.
Any advice would be grateful.
This looks like a PIVOT in sql server. Unfortunately mysql does not have this feature.
I can give you an approximate raw mysql query using GROUP_CONCAT. Assuming your table name is mytable.
SELECT
session_id,
batch,
GROUP_CONCAT(data ORDER BY column_id SEPARATOR ', ') AS dataList
FROM mytable
GROUP BY session_id, batch
Then you can split the aliased dataList column using given separator (here I've used ,).
You may change the separator according to the data contain in data column as you wish.
Hope this helps to you.

create chart with mysql and php

hi I'm trying to create a chart with php and mysql to show daily number of posts that generate Automatically using mysql queries.in database just we have date column.
I want some thing like this
date | posts count
------------+---------------
2017/05/02 | 5
2017/05/03 | 0
2017/05/04 | 1
2017/05/05 | 2
2017/05/06 | 0
2017/05/07 | 3
how to do this?
First of all you need to learn how to use these two:
Group by
COUNT
Since I have no idea about your table architecture here is a sample that you can adjust to your case:
select p.datePost, count(p.id) as postcounts
from posts p
group by p.datePost

MySQL: GROUP BY within ranges

I have a table with scores like this:
score | user
-------------------
2 | Mark
4 | Alex
3 | John
2 | Elliot
10 | Joe
5 | Dude
The table is gigantic in reality and the real scores goes from 1 to 25.
I need this:
range | counts
-------------------
1-2 | 2
3-4 | 2
5-6 | 1
7-8 | 0
9-10 | 1
I've found some MySQL solutions but they seemed to be pretty complex some of them even suggested UNION but performance is very important. As mentioned, the table is huge.
So I thought why don't you simply have a query like this:
SELECT COUNT(*) as counts FROM score_table GROUP BY score
I get this:
score | counts
-------------------
1 | 0
2 | 2
3 | 1
4 | 1
5 | 1
6 | 0
7 | 0
8 | 0
9 | 0
10 | 1
And then with PHP, sum the count of scores of the specific ranges?
Is this even worse for performance or is there a simple solution that I am missing?
Or you could probaly even make a JavaScript solution...
Your solution:
SELECT score, COUNT(*) as counts
FROM score_table
GROUP BY score
ORDER BY score;
However, this will not returns values of 0 for count. Assuming you have examples for all scores, then the full list of scores is not an issue. You just won't get counts of zero.
You can do what you want with something like:
select (case when score between 1 and 2 then '1-2'
when score between 3 and 4 then '3-4'
. . .
end) as scorerange, count(*) as count
from score_table
group by scorerange
order by min(score);
There is no reason to do additional processing in php. This type of query is quite typical for SQL.
EDIT:
According to the MySQL documentation, you can use a column alias in the group by. Here is the exact quote:
An alias can be used in a query select list to give a column a
different name. You can use the alias in GROUP BY, ORDER BY, or HAVING
clauses to refer to the column:
SELECT
SUM(
CASE
WHEN score between 1 and 2
THEN ...
Honestly, I can't tell you if this is faster than passing "SELECT COUNT(*) as counts FROM score_table GROUP BY score" into PHP and letting PHP handle it...but it add a level of flexibility to your setup. Create a three column table as 'group_ID', 'score','range'. insert values into it to get your groupings right
1,1,1-2
1,2,1-2
1,3,3-4
1,4,3-4
etc...
Join to it on score, group by range. THe addition of the 'group_ID' allows you to set groups...maybe have group 1 break it into groups of two, and let a group_ID = 2 be a 5 set range (or whatever you might want).
I find the table use like this is decently fast, requires little code changing, and can readily be added to if you require additional groupings or if the groupings change (if you do the groupings in code, the entire case section needs to be redone to change the groupings slightly).
How about this:
select concat((score + (1 * (score mod 2)))-1,'-',(score + (1 * (score mod 2)))) as score, count(*) from TBL1 group by (score + (1 * (score mod 2)))
You can see it working in this fiddle: http://sqlfiddle.com/#!2/215839/6
For the input
score | user
-------------------
2 | Mark
4 | Alex
3 | John
2 | Elliot
10 | Joe
5 | Dude
It generates this:
range | counts
-------------------
1-2 | 2
3-4 | 2
5-6 | 1
9-10 | 1
If you want a simple solution which is very powerful, add an extra field within your table and put a value in it for the score so 1 and 2 have the value 1, 3 and 4 has 2. With that you can group by that value. Only by inserting the score you've to add an extra field. So your table looks like this:
score | user | range
--------------------------
2 | Mark | 1
4 | Alex | 2
3 | John | 2
2 | Elliot | 1
10 | Joe | 5
5 | Dude | 3
Now you can do:
select count(score),range from table group by range;
This is always faster if you've an application where selecting has prior.
By inserting do this:
$scoreRange = 2;
$range = ceil($score/$scoreRange);

MYSQL: Get next 'n' results

Right now I have a PHP script that is fetching the first three results from a MYSQL database using:
SELECT * FROM table Order by DATE DESC LIMIT 3;
After that command I wanted PHP to fetch the next three results, initially I was going to use:
SELECT * FROM table Order by DATE DESC LIMIT 3,3;
However there will be a delay between the two commands which means that it is very possible that a new row will be inserted into the table during the delay. My first thought was to store the DATE value of the last result and then include a WHERE DATE > $stored_date but if entry 3 and 4 have the same date it will skip entry 4 and return results from 5 onward. This could be avoided using the primary key field which is an integer which increments automatically.
I am not sure which the best approach is, but I feel like there should be a more elegant and robust solution to this problem, however I am struggling to think of it.
Example table:
-------------------------------------------
| PrimaryKey | Data | Date |
-------------------------------------------
| 0 | abc | 2014-06-17 11:43:00 |
| 1 | def | 2014-06-17 12:43:00 |
| 2 | ghi | 2014-06-17 13:43:00 |
| 3 | jkl | 2014-06-17 13:56:00 |
| 4 | mno | 2014-06-17 14:23:00 |
| 5 | pqr | 2014-06-17 14:43:00 |
| 6 | stu | 2014-06-17 15:43:00 |
-------------------------------------------
Where Data is the column that I want.
Best will be using primary key and select like
SELECT * FROM table WHERE pk < $stored_pk Order by DATE DESC LIMIT 3;
And if you have automatically generated PK you should use ORDER BY pk it will be faster
Two options I can think of depending on what your script does:
You could either use transactions: performing these queries inside a transaction will give you a consistent view of the data.
Alternatively you could just use:
SELECT * FROM table Order by DATE DESC;
And only fetch the results as you need them.

Summarize db table player stats on output (multiple entries)

I'm trying to output a "scoreboard"/"standings" list of hockey players. I currently have a MySQL table like this:
statsID | matchID | playerID | goals | assists
120 | 2 | 3 | 4 | 1
121 | 2 | 4 | 2 | 2
122 | 3 | 3 | 0 | 3
So for each match the players gets added along with goals and assists. This means that there's multiple entries (several matches) for each player.
So basically, is there a good way to fetch the player data, summarize goals and assists (+ overall points) and output it in a list?
Right now, I have a basic query just outputting each row (as far as my current knowledge reaches). So how can I just output one entry of each player with his stats summarized?
Here's one approach:
SELECT t.playerID
, SUM(t.goals) AS total_goals
, SUM(t.assists) AS total_assists
FROM sometable t
GROUP BY t.playerID
ORDER BY t.playerID
Not clear what calculation you use for "overall points", if you are just adding goals and assists, then you can use this in the SELECT list:
, SUM(t.goals)+SUM(t.assists) AS overall_points
You need to use a group by clause.
SELECT playerID, SUM(goals + assist) overall points
FROM table_name
GROUP BY playerID

Categories