PHP - Concatenate rows from MySQL - javascript

My table is, I know that the table terrible but is old:
http://sqlfiddle.com/#!9/f2680/1
+----+-----------------------+----------+------+
| ID | COUNTRY | QUANTITY | EACH |
+----+-----------------------+----------+------+
| 1 | U.S.A | 1 | 12 |
| 2 | U.K. | 2 | 3 |
| 3 | GERMANY | NULL | 3 |
| 4 | FRANCE;GERMANY; U.S.A | 0 | 7 |
| 5 | U.S.A;GERMANY | 3 | 8 |
| 6 | GERMANY;FRANCE;U.S.A | 1 | 10 |
+----+-----------------------+----------+------+
<?php
include 'bd_cnx.php';
$ret =[['Test','Valori livrare']];
$sql = "SELECT SUBSTRING_INDEX(COUNTRY, ';', 1) AS COUNTRY,
SUM(COALESCE(IF(QUANTITY = NULL OR QUANTITY = 0,1,QUANTITY),1) * EACHCOL) AS PRICE
FROM table1
GROUP BY COUNTRY";
$result = $conn->query($sql);
if ($result->num_rows > 0){
while($row = $result->fetch_assoc()){
$ret[] =[$row['COUNTRY'], floatval($row['PRICE'])];
}
}
echo json_encode($ret);
?>
My SQL code returns rows: FRANCE=3, GERMANY=6, GERMANY=12, U.S.A=12, U.S.A=7
I want to group the resulted values from the COUNTRY column (to make them unique) and then make SUM and finaly to result the next form: FRANCE=3; GERMANY=18; U.S.A=19. I will introduce these rows in google chart in the next form: ['country','value'].
Thank you!

Use this query with additional select ... group by on the first query:
select COUNTRY, sum(PRICE) from(
SELECT
SUBSTRING_INDEX(COUNTRY, ';', 1) AS COUNTRY,
SUM(COALESCE(IF(QUANTITY = NULL OR QUANTITY = 0,1,QUANTITY),1) * EACHCOL) AS PRICE
FROM table1
GROUP BY COUNTRY) as t
group by COUNTRY;

Related

How to chart missing data in chartjs

The problem
I want to create a time based, stacked bar chart using Chartjs but I have missing time values. I have two questions:
1.) How can I fill in the missing data with zeroes either in the SQL query or while I am building the arrays from the Ajax response?
2.) Is there a better way to visualize the data using chartjs rather than using a stacked chart that does not require the missing data?
The following is a simple explanation summarized by month. In production, this could dynamically change to a weekly or daily summarization. Working example available on jsFiddle
The desired outcome:
+----+
|Bill| +----+ +----+
| | |Bill| |Bill|
|----| |----| +----+
|Joe | |Mary| |Mary|
+----+ +----+ +----+
Jan Feb Mar
This is a hyper simplified version of the database table to illustrate the problem.
Orders table:
+--------+---------+-------+
|Salesman| Order # | Month |
+--------+---------+-------+
|Bill | 10500 | Jan |
|Bill | 10501 | Jan |
|Joe | 10867 | Jan |
|Mary | 10892 | Feb |
|Bill | 12527 | Feb |
|Mary | 12741 | Mar |
|Bill | 13292 | Mar |
+--------+---------+-------+
SELECT salesman, month, count(*) as orders
FROM orders
GROUP BY month, salesman
ORDER BY month, Salesman
+------+----------+--------+
|Month | Salesman | Orders |
+------+----------+--------+
|Jan | Bill | 2 |
|Jan | Joe | 1 |
|Feb | Mary | 1 |
|Feb | Bill | 1 |
|Mar | Mary | 1 |
|Mar | Bill | 1 |
+------+----------+--------+
Mary has no entry for Jan and Joe has no entries for Feb or Mar. When I build the array from the ajax response, my chart.data.labels array for the x-values are [Jan, Feb, Mar] but the chart.datasets[n].data for the y-values look like this:
Bill : [2,1,1]
Joe : [1]
Mary: [1,1]
They should look like this:
Bill : [2,1,1]
Joe : [1,0,0]
Mary: [0,1,1]
#nbk provided the clue to the resolution with a pivot table. Here's my solution, a PHP function in the controller to dynamically build SQL for a pivot table.
Might move it to a general purpose utility lib in the future.
private function pivotTable($table, $pivotColumn, $pivotLabel, $whereClause, $aggregate="count"){
$returnValue = [];
// validate parms exist
if ((isset($table) != true) ||
(isset($pivotLabel) != true) ||
(isset($pivotColumn) != true)) {
$returnValue['error'] = true;
$returnValue['message'] = 'Invalid parameter';
return $returnValue ;
}
// build the SQL to get the column names and column count
$qry = "SELECT DISTINCT {$pivotColumn} FROM {$table} ";
$where = (isset($whereClause)) ? "WHERE {$whereClause} " : "";
$order = "ORDER BY {$pivotColumn};";
// execute the query
$columns = $this->db->query($qry . $where . $order);
// no columns to pivot
if( $columns->num_rows() < 1) {
$returnValue['error'] = true;
$returnValue['message'] = 'No columns to pivot';
return $returnValue ;
}
// too many columns to pivot
if($columns->num_rows() > 50) {
$returnValue['error'] = true;
$returnValue['message'] = 'Pivot would result in more than 50 columns';
return $returnValue ;
};
// build pivot query
$i = 0;
$pivotQry = "SELECT {$pivotLabel} ";
foreach($columns->result_array() as $column) {
$pivotQry .= ",\r\n{$aggregate}( IF ( {$pivotColumn} = '{$column[$pivotColumn]}', {$pivotColumn}, NULL ) ) as {$column[$pivotColumn]} ";
}
$pivotQry .= "\r\nFROM {$table} \r\n";
$pivotQry .= $where;
$pivotQry .= "GROUP BY {$pivotLabel} ";
$returnValue['error'] = false;
$returnValue['message'] = 'Ok';
$returnValue['sql'] = $pivotQry;
return $returnValue ;
}

Solution for non numeric dynamic input field names

I have students, student_subject, subjects and results tables.
Students Table
| id | name |
|----|-------|
| 1 | John |
| 2 | Sara |
| 3 | Smith |
Subjects Table
| id | name |
|----|-------------|
| 1 | Science |
| 2 | Mathematics |
| 3 | English |
Student_subject Table
| id | student_id | subject_id |
|----|------------|------------|
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 2 | 1 |
| 4 | 3 | 1 |
Results Table
| id | student_subject_id | result |
|----|--------------------|--------|
| 1 | 1 | 45 |
| 2 | 2 | 25 |
| 3 | 3 | 65 |
| 4 | 4 | 45 |
There are separate forms to insert students (with selecting subjects), subjects and results. I got a problem creating the form to add results for a student.
The form consists of form inputs listing down all the subjects of the student to enter results. For a specific student, the form to insert results may look like this(after looping the students subjects). The name attribute contains the Student_subject table id value. I add the name to this value because In the database I need to have reference for the student_subject table in the database.
<form>
<input type="text" class="form-control" name="1" required>
<input type="text" class="form-control" name="2" required>
</form>
I want to know this approach is correct or wrong to add results to students?
If not what are the changes I have to do in database and forms.

MySQL select AND on multiple rows and multiple fields

I have a table:
+ --------------------------+---------------------------+--------------+--------+
| ID | SKU_ID | DKEY | DVAL |
+ --------------------------+---------------------------+--------------+--------+
| cjamtti7z00aivmv4ffc9ttuw | cjamtti7z00afvmv4ai5i0ffy | Part | A2030 |
| cjamtti7z00ajvmv4gztx7hq8 | cjamtti7z00afvmv4ai5i0ffy | Description | Single |
| cjamtti7z00akvmv4zvrvtazj | cjamtti7z00afvmv4ai5i0ffy | Length mm | 50 |
| cjamtti7z00alvmv4jxnryckh | cjamtti7z00afvmv4ai5i0ffy | Line Dia. mm | 6 - 10 |
+ --------------------------+---------------------------+--------------+--------+
I want to create a query that searches for SKUs that match a provided object:
{
'Fixing Hole Depth(mm)': '13 Min - 18 Max',
'Inside Dia. (mm)' : '11',
'Weight (g)' : '3'
}
I can't seem to find a way to combine AND and OR clauses that gives me the desired result.
To summarise, I need the SKU_IDs that match ALL the criteria in the object.
In basic SQL it can be achieved with GROUP BY + COUNT.
SELECT SKU_ID
FROM your_table
WHERE (DKEY = 'Fixing Hole Depth(mm)' AND DVAL = '13 Min - 18 Max,') OR
(DKEY = 'Inside Dia. (mm)' AND DVAL = '11,') OR
(DKEY = 'Weight (g)' AND DVAL = '3')
GROUP BY SKU_ID
HAVING count(*) = 3
It's required to have each SKU_ID + DKEY to be unique(otherwise you may have 3 values for DKEY = 'Weight(g)' for the same SKU_ID and query will not work as expected)
Maybe there is some less verbose way but it should be RDBMS-dependant
Your where clause can combine AND and OR easily, if you nest them correctly in brackets (). Try that.

Binding Model.ID to Checkbox list and post Model.X, Model.Y, etc. properties to Controller

In an MVC application I joined multiple tables and returned it from Controller to View as shown below:
| EmployeeID | ControlID | DoorAddress | DoorID | DoorName |
------------------------------------------------------------
| 921 | 1 | 1 | 101 | Door 1 |
| 921 | 1 | 2 | 102 | Door 2 |
| 921 | 1 | 3 | 103 | Door 3 |
| 921 | 1 | 4 | 104 | Door 4 |
------------------------------------------------------------
Controller:
public ActionResult Edit(int? id)
{
// Create and execute raw SQL query.
string query = "SELECT a.EmployeeID, a.ControlID, a.DoorAddress, t.DoorID, t.DoorName FROM TEmpAccess AS a " +
"INNER JOIN TDoor AS t ON a.ControlID = t.ControlID and a.DoorAddress = t.DoorAddress where EmployeeID = " + id.ToString();
IEnumerable<EmpAccessViewModel> data = db.Database.SqlQuery<EmpAccessViewModel>(query);
return View(data.ToList());
}
I want to bind DoorName values (Door 1, Door 2, Door 3, Door 4) to a checkbox list and let the user to select them. After that, I want to pass corresponding EmployeeID, ControlID, DoorAddress, DoorID values of the the selected door to the Controller. For example if the user selects Door 1 and Door 3, then I will pass these values below to the Controller:
| EmployeeID | ControlID | DoorAddress | DoorID |
-------------------------------------------------
| 921 | 1 | 1 | 101 |
| 921 | 1 | 3 | 103 |
-------------------------------------------------
By using razor syntax or javascript in the view, how can I do this? Thanks in advance.
If you want a checkbox at the beginning of the Table in the view which is to be passed to the controller and each row is uniquely identified by the DoorID you could try something like this.
in View
<table>
#foreach (var item in Model)
{
<tr>
<td><input type="checkbox" value="#item.DoorID" name="doorid" /></td>
<td>#item.EmployeeID</td>
<td>#item.ControlID</td>
<td>#item.DoorName</td>
</tr>
}
</table>
In controller
public void ControllerName(int[] doorid)
{
foreach(var item in doorid)
//do something
}

how can I associate one variable with the other two (mysql)?

I have four tables in mysql (object, type, price, date)
all of them have two coloumns: "id" and "variable"
for example:
Object table
+----+-----------+
| id | variable |
+----+-----------+
| 1 | shop1 |
+----+-----------+
| 2 | shop2 |
+----+-----------+
type table
+----+----------+
| id | variable |
+----+----------+
| 1 | lemon |
+----+----------+
| 2 | potato |
+----+----------+
Date table
+----+------------+
| id | variable |
+----+------------+
| 1 | 2014-10-11 |
+----+------------+
| 2 | 2014-12-11 |
+----+------------+
price table
+----+------------+
| id | variable |
+----+------------+
| 1 | 5000 |
+----+------------+
| 2 | 2000 |
+----+------------+
| 3 | 4000 |
+----+------------+
| 4 | 3000 |
+----+------------+
And what we really need in browser view:
Shop1:
+--------+------------+------------+
| | 2014-10-11 | 2014-12-11 |
+--------+------------+------------+
| lemon | 5000 | 3000 |
+--------+------------+------------+
| potato | 2000 | 4000 |
+--------+------------+------------+
Price is a variable and could be changed like an other variables (dates, type), columns of dates or types could be much more - (max - 5)
This table looks like Excel. But the price must depend on other variables, because other objects could use the same id of price.
First loop Through type table and get the ID
select * from type
Then Loop through ID's as $id
Then In loop you need to query each table for each required value.for example
select variable from price where ID = $id
select variable from date where ID = $id

Categories