Yii2 math in \yii\db\Query() - yii2

I want to do some math (divide, minus, plus...), and two or more fields' values are using a Yii database query like below. Can I do it like this?
$data = (new \yii\db\Query())
->select([
'date',
'SUM( IF(status = "Passed", 1, 0) ) AS passed',
'SUM( IF(status = "Failed", 1, 0) ) AS failed',
'SUM( IF(status = "On Hold", 1, 0) ) AS onhold',
'passed/onhold as selfsubmit',
'COUNT(*) AS total'
])
->from('qa3d')
->groupBy('date')
->all();

First of all, you cannot do arithmetics (math) with aliases in the same query with MySQL. That is mentioned here as well.
But you can calculate using the yii\db\Expression class, because with that, the framework won't try to escape the expression as MySQL columns.
So basically you have to select the expression without the aliases and with the Expression class.
For example:
$data = (new \yii\db\Query())
->select([
'date',
'SUM( IF(status = "Passed", 1, 0) ) AS passed',
'SUM( IF(status = "Failed", 1, 0) ) AS failed',
'SUM( IF(status = "On Hold", 1, 0) ) AS onhold',
new \yii\db\Expression('SUM( IF(status = "Passed", 1, 0) ) / SUM( IF(status = "On Hold", 1, 0) ) AS selfsubmit'),
'COUNT(*) AS total'
])
->from('qa3d')
->groupBy('date')
->all();

Related

How to make Laravel eloquent request with 1 filter on many fields

In my Laravel 5.7/ mysql app I make request on a form with 10 filter inputs,
one of them ($filter_search) if non empty must be compared with all fields(string, number,
date, ref to fields of other tables) in resulting listing.
I made scope on this table fields:
public function scopeGetBySearch($query, $search = null)
{
if (empty($search)) {
return $query;
}
$tb= with(new StorageSpace)->getTable();
return $query->where(
$tb.'.number', $search
) ->orWhere(function ($query) use ($search, $tb) {
$query->where( $tb.".notes", 'like', '%'.$search.'%' )
->orWhere($tb.".selling_range", $search)
->orWhere($tb.".actual_storage_rent", $search)
->orWhere($tb.".insurance_vat", $search)
// ->havingRaw("job_ref_no", $search)
})
But I have a problem how can I set filter on job_ref_no field from other table :
$storageSpacesCollection = StorageSpace
::getByStatus($filter_status)
->getById($relatedStorageSpacesArray)
->getByLocationId($filter_location_id, 'warehouses')
->getByCapacityCategoryId($filter_capacity_category_id, 'storage_capacities')
->getByLevel($filter_level)
->getByNumber($filter_number, true)
->orderBy('storage_spaces.id', 'asc')
->getByStorageCapacityId($filter_storage_capacity_id)
->getByClientId($filter_client_id)
->getByColorId($filter_color_id)
->getBySearch($filter_search)
// ->havingRaw("job_ref_no = " . $filter_search)
->leftJoin( 'storage_capacities', 'storage_capacities.id', '=', 'storage_spaces.storage_capacity_id' )
->leftJoin( 'warehouses', 'warehouses.id', '=', 'storage_spaces.warehouse_id' )
->leftJoin( 'clients', 'clients.id', '=', 'storage_spaces.client_id')
->select(
"storage_spaces.*",
\DB::raw( "CONCAT(storage_capacities.count, ' ', storage_capacities.sqft ) as storage_capacity_name" ),
\DB::raw("( SELECT check_ins.job_ref_no FROM check_ins WHERE // I got job_ref_no field in subquesry check_ins.storage_space_id=storage_spaces.id ORDER BY check_ins.id ASC limit 1 ) AS job_ref_no"),
"warehouses.name as warehouse_name",
"clients.full_name as client_full_name")
->get();
havingRaw does not work both in the scope and in the request above if to uncomment it.
I tried to use addSelect, like:
But with request :
$storageSpacesCollection = StorageSpace
::getByStatus($filter_status)
->whereRaw('storage_spaces.id <= 8') // DEBUGGING
->getById($relatedStorageSpacesArray)
->getByLocationId($filter_location_id, 'warehouses')
->getByCapacityCategoryId($filter_capacity_category_id, 'storage_capacities')
->getByLevel($filter_level)
->getByNumber($filter_number, true)
->orderBy('storage_spaces.id', 'asc')
->getByStorageCapacityId($filter_storage_capacity_id)
->getByClientId($filter_client_id)
->getByColorId($filter_color_id)
->getBySearch($filter_search)
// ->havingRaw("job_ref_no = " . $filter_search)
->leftJoin( 'storage_capacities', 'storage_capacities.id', '=', 'storage_spaces.storage_capacity_id' )
->leftJoin( 'warehouses', 'warehouses.id', '=', 'storage_spaces.warehouse_id' )
->leftJoin( 'clients', 'clients.id', '=', 'storage_spaces.client_id')
->select(
"storage_spaces.*",
\DB::raw( "CONCAT(storage_capacities.count, ' ', storage_capacities.sqft ) as storage_capacity_name" ),
"warehouses.name as warehouse_name",
"clients.full_name as client_full_name")
->addSelect([
'job_ref_no' => CheckIn::selectRaw('job_ref_no')->whereColumn('check_ins.storage_space_id', 'storage_spaces.id'),
])
->get();
But I got an error:
local.ERROR: stripos() expects parameter 1 to be string, object given {"userId":11,"email":"nilovsergey#yahoo.com","exception":"[object] (ErrorException(code: 0): stripos() expects parameter 1 to be string, object given at /mnt/_work_sdb8/wwwroot/lar/the-box-booking/vendor/laravel/framework/src/Illuminate/Database/Query/Grammars/Grammar.php:1031)
[stacktrace]
#0 [internal function]: Illuminate\\Foundation\\Bootstrap\\HandleExceptions->handleError(2, 'stripos() expec...', '/mnt/_work_sdb8...', 1031, Array)
#1 /mnt/_work_sdb8/wwwroot/lar/the-box-booking/vendor/laravel/framework/src/Illuminate/Database/Query/Grammars/Grammar.php(1031): stripos(Object(Illuminate\\Database\\Eloquent\\Builder), ' as ')
#2 [internal function]: Illuminate\\Database\\Query\\Grammars\\Grammar->wrap(Object(Illuminate\\Database\\Eloquent\\Builder))
Which way is valid ?
MODIFIED BLOCK:
I try to create sql I need manually.
With Laravel request :
$storageSpacesCollection = StorageSpace
::getByStatus($filter_status)
->whereRaw('storage_spaces.id <= 8') // DEBUGGING
->getById($relatedStorageSpacesArray)
->getByLocationId($filter_location_id, 'warehouses')
->getByCapacityCategoryId($filter_capacity_category_id, 'storage_capacities')
->getByLevel($filter_level)
->getByNumber($filter_number, true)
->orderBy('storage_spaces.id', 'asc')
->getByStorageCapacityId($filter_storage_capacity_id)
->getByClientId($filter_client_id)
->getByColorId($filter_color_id)
->getBySearch($filter_search)
->leftJoin( 'storage_capacities', 'storage_capacities.id', '=', 'storage_spaces.storage_capacity_id' )
->leftJoin( 'warehouses', 'warehouses.id', '=', 'storage_spaces.warehouse_id' )
->leftJoin( 'clients', 'clients.id', '=', 'storage_spaces.client_id')
->select(
"storage_spaces.*",
\DB::raw( "CONCAT(storage_capacities.count, ' ', storage_capacities.sqft ) as storage_capacity_name" ),
\DB::raw("( SELECT check_ins.job_ref_no FROM check_ins WHERE check_ins.storage_space_id=storage_spaces.id ORDER BY check_ins.id ASC limit 1 ) AS job_ref_no"),
"warehouses.name as warehouse_name",
"clients.full_name as client_full_name")
->get();
And tracing I see sql statement with job_ref_no column :
SELECT `storage_spaces`.*, CONCAT(storage_capacities.count, ' ', storage_capacities.sqft ) AS storage_capacity_name, ( SELECT check_ins.job_ref_no
FROM check_ins
WHERE check_ins.storage_space_id=storage_spaces.id
ORDER BY check_ins.id ASC limit 1 ) AS job_ref_no, `warehouses`.`name` AS `warehouse_name`, `clients`.`full_name` AS `client_full_name`
FROM `storage_spaces`
LEFT JOIN `storage_capacities` on `storage_capacities`.`id` = `storage_spaces`.`storage_capacity_id`
LEFT JOIN `warehouses` on `warehouses`.`id` = `storage_spaces`.`warehouse_id`
LEFT JOIN `clients` on `clients`.`id` = `storage_spaces`.`client_id`
WHERE storage_spaces.id <= 8 AND (`storage_spaces`.`number` = '999' OR
(`storage_spaces`.`notes` like '%999%' OR
`storage_spaces`.`selling_range` = '999' OR
`storage_spaces`.`actual_storage_rent` = '999' OR
`storage_spaces`.`insurance_vat` = '999') )
ORDER BY `storage_spaces`.`id` asc
I want to set filter on job_ref_no column manually :
SELECT `storage_spaces`.*, CONCAT(storage_capacities.count, ' ', storage_capacities.sqft ) AS storage_capacity_name, ( SELECT check_ins.job_ref_no
FROM check_ins
WHERE check_ins.storage_space_id=storage_spaces.id
ORDER BY check_ins.id ASC limit 1 ) AS job_ref_no, `warehouses`.`name` AS `warehouse_name`, `clients`.`full_name` AS `client_full_name`
FROM `storage_spaces`
LEFT JOIN `storage_capacities` on `storage_capacities`.`id` = `storage_spaces`.`storage_capacity_id`
LEFT JOIN `warehouses` on `warehouses`.`id` = `storage_spaces`.`warehouse_id`
LEFT JOIN `clients` on `clients`.`id` = `storage_spaces`.`client_id`
WHERE storage_spaces.id <= 8 AND (`storage_spaces`.`number` = '999' OR
(`storage_spaces`.`notes` like '%999%' OR
`storage_spaces`.`selling_range` = '999' OR
`storage_spaces`.`actual_storage_rent` = '999' OR
`storage_spaces`.`insurance_vat` = '999' OR
job_ref_no = '999' ) // I added this line #
)
ORDER BY `storage_spaces`.`id` asc
But I got error :
Error in query (1054): Unknown column 'job_ref_no' in 'where clause'
Which is valid way in raw sql and how it can be implemented with eloquent ?
MODIFIED BLOCK # 2:
I try to make with join:
$storageSpacesCollection = StorageSpace
::getByStatus($filter_status)
->getById($relatedStorageSpacesArray)
->getByLocationId($filter_location_id, 'warehouses')
->getByCapacityCategoryId($filter_capacity_category_id, 'storage_capacities')
->getByLevel($filter_level)
->getByNumber($filter_number, true)
->orderBy('storage_spaces.id', 'asc')
->getByStorageCapacityId($filter_storage_capacity_id)
->getByClientId($filter_client_id)
->getByColorId($filter_color_id)
->getBySearch($filter_search)
->leftJoin( 'storage_capacities', 'storage_capacities.id', '=', 'storage_spaces.storage_capacity_id' )
->leftJoin( 'warehouses', 'warehouses.id', '=', 'storage_spaces.warehouse_id' )
->leftJoin( 'clients', 'clients.id', '=', 'storage_spaces.client_id')
->leftJoin( 'check_ins', 'check_ins.storage_space_id', '=', 'storage_spaces.id') // I ADDED THIS LINE
->select(
"storage_spaces.*",
\DB::raw( "CONCAT(storage_capacities.count, ' ', storage_capacities.sqft ) as storage_capacity_name" ),
// \DB::raw("( SELECT check_ins.job_ref_no FROM check_ins WHERE check_ins.storage_space_id=storage_spaces.id ORDER BY check_ins.id ASC limit 1 ) AS job_ref_no"),
"warehouses.name as warehouse_name",
"check_ins.job_ref_no as job_ref_no",
"clients.full_name as client_full_name")
->distinct()
->get();
and I have a sql :
SELECT distinct `storage_spaces`.*, CONCAT(storage_capacities.count, ' ', storage_capacities.sqft ) AS storage_capacity_name,
`warehouses`.`name` AS `warehouse_name`, `check_ins`.`job_ref_no` AS `job_ref_no`, `clients`.`full_name` AS `client_full_name`
FROM `storage_spaces`
LEFT JOIN `storage_capacities` on `storage_capacities`.`id` = `storage_spaces`.`storage_capacity_id`
LEFT JOIN `warehouses` on `warehouses`.`id` = `storage_spaces`.`warehouse_id`
LEFT JOIN `clients` on `clients`.`id` = `storage_spaces`.`client_id`
LEFT JOIN `check_ins` on `check_ins`.`storage_space_id` = `storage_spaces`.`id`
WHERE ( `storage_spaces`.`number` = 'S1-102' OR (`storage_spaces`.`notes` like '%S1-102%' OR `storage_spaces`.`selling_range` = 'S1-102' OR
`storage_spaces`.`actual_storage_rent` = 'S1-102' OR `storage_spaces`.`insurance_vat` = 'S1-102' OR `job_ref_no` = 'S1-102') )
ORDER BY `storage_spaces`.`id` asc
I have have different results
I need to get only last row from check_ins, that is why in my request I have limit 1:
\DB::raw("( SELECT check_ins.job_ref_no FROM check_ins WHERE check_ins.storage_space_id=storage_spaces.id ORDER BY check_ins.id ASC limit 1 ) AS job_ref_no"),
that is why have have several rows of as storage_spaces as all check_ins ae joined
2) I have all rows from storage_spaces and I do not see why
I tried to change leftJoin with Join /rightJoin but it did not help...
Thanks!
You need to set the join into the main query instead of select query because in select query it's not a actual column which you set into the where condition.
I found a decision addin in scope :
->orWhereRaw("(SELECT check_ins.job_ref_no FROM check_ins WHERE
check_ins.storage_space_id=storage_spaces.id ORDER BY check_ins.id ASC LIMIT 1) = '".$search."'")
and that works for me.

MySQL FIND_IN_SET search result needed in original sequence

I am using FIND_IN_SET in MySQL as below :
SELECT
color, b.id
FROM cards b
where FIND_IN_SET(b.color, 'gold,gold,bronze,silver,silver') > 0
GROUP BY b.id
ORDER BY RAND()
limit 5;
And I get output as below :
However, I want to get cards in the same sequence as in the parameter string supplied to FIND_IN_SET i.e.
gold, gold, bronze, silver, silver
So the first output row should be of gold color, then another gold, then bronze and so on - in the same sequence without any random search.
I cannot have self join as it's a big table.
You will need to do this using a UNION of 3 queries to find random 'gold', 'silver' and 'bronze' medallists, and then order those results using FIELD:
SELECT color, id
FROM (
(
SELECT color, id
FROM cards
WHERE color = 'gold'
ORDER BY RAND()
LIMIT 2
)
UNION ALL
(
SELECT color, id
FROM cards
WHERE color = 'bronze'
ORDER BY RAND()
LIMIT 1
)
UNION ALL
(
SELECT color, id
FROM cards
WHERE color = 'silver'
ORDER BY RAND()
LIMIT 2
)
) m
ORDER BY FIELD(color, 'gold', 'bronze', 'silver')
Demo on SQLFiddle
Here's a way you might implement this as a combination of PHP/MySQL:
$pack_sql_comma_separated = 'gold,silver,gold,gold,silver,gold';
$colors = explode(',', $pack_sql_comma_separated);
$counts = array_count_values($colors);
$sql = "SELECT color, id FROM (";
$subqueries = [];
foreach ($counts as $color => $count) {
$subqueries[] = "(
SELECT color, id
FROM cards
WHERE color = '$color'
ORDER BY RAND()
LIMIT $count
)";
}
$sql .= implode(' UNION ALL ', $subqueries) . ') m';
// run SQL query
// ...
// assume all query results read into $rows according to medal colour, something like this
$rows = array('gold' => array(array('id' => 20),
array('id' => 5),
array('id' => 4),
array('id' => 27)
),
'silver' => array(array('id' => 19),
array('id' => 11)
)
);
//display in required order
foreach ($colors as $color) {
$card = array_shift($rows[$color]);
echo "$color {$card['id']}\n";
}
Demo on 3v4l.org

MySQL getting and Invalid use of group function

I'm trying to count the result of tc.personnel_id if there's more than 1 result, then the output is 1. And then finally, it will get the sum. But I am getting an "Invalid use of group function" error when i execute this code. Any help will be appreciated.
SELECT tv.id,
tv.vesselName,
SUM(IF(tpi.returningCrew = 0, 1,
IF(
COUNT(tc.personnel_id) > 1, 1, 0)
)
) AS ex_crew,
SUM(IF(tpi.returningCrew = 1, 1, 0)) AS new_hire
FROM tbl_vessels AS tv
LEFT JOIN tbl_personnel_info AS tpi
ON tv.id = tpi.lastJoinedVsl
LEFT JOIN tbl_contracts AS tc
ON tpi.id = tc.personnel_id
LEFT JOIN tbl_management AS tm
ON tm.id = tv.management
WHERE tpi.emp_status = 'ON-BOARD'
AND tc.status = 'ACTIVE'
AND tv.trade_route = 'WORLD WIDE'
AND tm.management = 'TOKYO'
GROUP BY vesselName;
Aggregate functions can not be nested. So something like SUM(.. COUNT(..) ..) is not possible. You might try something like this:
SELECT tv.id,
tv.vesselName,
CASE WHEN COUNT(tc.personnel_id) > 1
THEN SUM(IF(tpi.returningCrew = 0, 1, 1)
ELSE SUM(IF(tpi.returningCrew = 0, 1, 0)
END AS ex_crew,
SUM(IF(tpi.returningCrew = 1, 1, 0)) AS new_hire
FROM [..]
SUM(IF(tpi.returningCrew = 0, 1, 1) can be rewriten to SUM(1) or to COUNT(*).
SUM(IF(tpi.returningCrew = 0, 1, 0) cann also be rewritten to SUM(tpi.returningCrew = 0)
And SUM(IF(tpi.returningCrew = 1, 1, 0)) to SUM(tpi.returningCrew = 1)
So the final select could be:
SELECT tv.id,
tv.vesselName,
CASE WHEN COUNT(tc.personnel_id) > 1
THEN COUNT(*)
ELSE SUM(tpi.returningCrew = 0)
END AS ex_crew,
SUM(tpi.returningCrew = 1) AS new_hire
FROM [..]

include an aliased field in mysql to another alias

i have a table that stores values in hour-minute float format and im pulling the data from the database while converting hour-minute float to minutes using this query.
SELECT
DailyTimelog.id,
DailyTimelog.payroll_cut_off_id,
DailyTimelog.employee_id,
DailyTimelog.work_shift_id,
DailyTimelog.employee_status,
DailyTimelog.timelog_date,
DailyTimelog.is_rest_day,
DailyTimelog.is_on_leave,
DailyTimelog.is_holiday,
DailyTimelog.is_regular_holiday,
DailyTimelog.is_special_holiday,
DailyTimelog.is_absent,
(
(SUBSTRING_INDEX(tardiness_hours, '.', 1)*60)
+(
case when (INSTR(tardiness_hours, '.') = 0)
THEN 0
ELSE SUBSTRING_INDEX(tardiness_hours, '.', -1)
END)
) as tardiness_hours,
(
(SUBSTRING_INDEX(leave_hours, '.', 1)*60)
+(
case when (INSTR(leave_hours, '.') = 0)
THEN 0
ELSE SUBSTRING_INDEX(leave_hours, '.', -1)
END)
) as leave_hours,
DailyTimelog.leave_credit_used,
(
(SUBSTRING_INDEX(normal_work_hrs, '.', 1)*60)
+(
case when (INSTR(normal_work_hrs, '.') = 0)
THEN 0
ELSE SUBSTRING_INDEX(normal_work_hrs, '.', -1)
END)
) as normal_work_hrs,
(
(SUBSTRING_INDEX(overtime_work_hrs, '.', 1)*60)
+(
case when (INSTR(overtime_work_hrs, '.') = 0)
THEN 0
ELSE SUBSTRING_INDEX(overtime_work_hrs, '.', -1)
END)
) as overtime_work_hrs,
(
(SUBSTRING_INDEX(night_premium_work_hrs, '.', 1)*60)
+(
case when (INSTR(night_premium_work_hrs, '.') = 0)
THEN 0
ELSE SUBSTRING_INDEX(night_premium_work_hrs, '.', -1)
END)
) as night_premium_work_hrs
FROM `daily_timelogs` as DailyTimelog WHERE DailyTimelog.payroll_cut_off_id = 404
when i output the data using print_f() i get something like this:
[DailyTimelog] => Array
(
[id] => 93608
[payroll_cut_off_id] => 404
[employee_id] => 126
[work_shift_id] => 11
[employee_status] => 2
[timelog_date] => 2016-03-27
[is_rest_day] => 1
[is_on_leave] =>
[is_holiday] =>
[is_regular_holiday] =>
[is_special_holiday] =>
[is_absent] =>
[leave_credit_used] => 0
)
[0] => Array
(
[tardiness_hours] => 0
[leave_hours] => 0
[normal_work_hrs] => 0
[overtime_work_hrs] => 0
[night_premium_work_hrs] => 0
)
is there a way to include index 0 to the DailyTimelogs index while still on mysql?

Google chart values from different times

Working on a google line chart. Having the problem that two of the values (T_Temperatur) And (T_Badende_per_Time) is inserted into the database at the same time with one submit. But not T_Lufttemperatur. That is creating problem with the chart, which is also showing the nulls. So this is my sql:
This is the google chart:
Code:
<?php
$con=mysql_connect("localhost","root","") or die("Failed to connect with database!!!!");
mysql_select_db("nih_bw", $con);
$sth = mysql_query("
SELECT routines.date, routines.time,
SUM( IF( measurements.title = 'T_Temperatur', CAST( REPLACE( routines.value, ',', '.' ) AS DECIMAL( 18, 2 ) ), 0 ) ) AS Temperatur,
SUM( IF( measurements.title = 'T_Badende_per_Time', CAST( REPLACE( routines.value, ',', '.' ) AS DECIMAL( 18, 2 ) ), 0 ) ) AS Badende,
SUM( IF( measurements.title = 'T_Luft_Temperatur', CAST( REPLACE( routines.value, ',', '.' ) AS DECIMAL( 18, 2 ) ), 0 ) ) AS Luft
FROM routines
INNER JOIN measure_routine ON routines.id = measure_routine.routine_id
INNER JOIN measurements ON measure_routine.measure_id = measurements.id
GROUP BY routines.date, routines.time
ORDER BY routines.date, routines.time;
;");
$rows = array();
//flag is not needed
$flag = true;
$table = array();
$table['cols'] = array(
array('label' => 'routines.date' & 'routines.time', 'type' => 'datetime'),
array('label' => 'Temperatur', 'type' => 'number'),
array('label' => 'Badende', 'type' => 'number'),
array('label' => 'Luft', 'type' => 'number'),
);
$rows = array();
while($r = mysql_fetch_assoc($sth)) {
$temp = array();
// assumes dates are in the format "yyyy-MM-dd"
$dateString = $r['date'];
$dateArray = explode('-', $dateString);
$year = $dateArray[0];
$month = $dateArray[1] - 1; // subtract 1 to convert to javascript's 0-indexed months
$day = $dateArray[2];
// assumes time is in the format "hh:mm:ss"
$timeString = $r['time'];
$timeArray = explode(':', $timeString);
$hours = $timeArray[0];
$minutes = $timeArray[1];
$seconds = $timeArray[2];
$temp = array();
$temp[] = array('v' => "Date($year, $month, $day, $hours, $minutes, $seconds)");
$temp[] = array('v' => (string) $r['Temperatur']);
$temp[] = array('v' => (string) $r['Badende']);
$temp[] = array('v' => (string) $r['Luft']);
$rows[] = array('c' => $temp);
}
$table['rows'] = $rows;
$jsonTable = json_encode($table);
// echo $jsonTable;
?>
<html>
<head>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = new google.visualization.DataTable(<?=$jsonTable?>);
var options = {
/*width: 900, height: 900, */
title: 'Visualization',
curveType: 'function',
legend: { position: 'bottom' },
pointSize: 5,
vAxis: {title: "Values", titleTextStyle: {italic: false}},
hAxis: {title: "Time", titleTextStyle: {italic: false}},
explorer: {
actions: ['dragToZoom', 'rightClickToReset'],
axis: 'vertical'}
};
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
</script>
</head>
<body>
<div id="chart_div" style="width: 900px; height: 500px;"></div>
</body>
</html>
jsontable:
{"cols":[{"label":"routines.dade","type":"datetime"},{"label":"Temperatur","type":"number"},
{"label":"Badende","type":"number"},{"label":"Luft","type":"number"}],"rows":[{"c":
[{"v":"Date(2014, 3, 02, 09, 04, 12)"},{"v":"29.23"},{"v":"55.00"},{"v":""}]},{"c":
[{"v":"Date(2014, 3, 02, 10, 04, 01)"},{"v":"23.34"},{"v":"34.00"},{"v":""}]},{"c":
[{"v":"Date(2014, 3, 02, 10, 04, 39)"},{"v":"43.54"},{"v":"39.00"},{"v":""}]},{"c":
[{"v":"Date(2014, 3, 02, 10, 04, 53)"},{"v":""},{"v":""},{"v":"23.23"}]}]}
Please feel free to ask if you need more info provided.
Try replacing the 0's in the query with nulls:
SELECT routines.date, routines.time,
SUM( IF( measurements.title = 'T_Temperatur', CAST( REPLACE( routines.value, ',', '.' ) AS DECIMAL( 18, 2 ) ), null ) ) AS Temperatur,
SUM( IF( measurements.title = 'T_Badende_per_Time', CAST( REPLACE( routines.value, ',', '.' ) AS DECIMAL( 18, 2 ) ), null ) ) AS Badende,
SUM( IF( measurements.title = 'T_Luft_Temperatur', CAST( REPLACE( routines.value, ',', '.' ) AS DECIMAL( 18, 2 ) ), null ) ) AS Luft
FROM routines
INNER JOIN measure_routine ON routines.id = measure_routine.routine_id
INNER JOIN measurements ON measure_routine.measure_id = measurements.id
GROUP BY routines.date, routines.time
ORDER BY routines.date, routines.time;
[EDIT - added PHP code to avoid casting the numbers as strings]
When inputting your data, don't cast them as strings:
$temp[] = array('v' => $r['Temperatur']);
$temp[] = array('v' => $r['Badende']);
$temp[] = array('v' => $r['Luft']);
and use the JSON_NUMERIC_CHECK option in the json_encode call:
$jsonTable = json_encode($table, JSON_NUMERIC_CHECK);