php mysql query dynamic Group by value - php

Hi I have a mysql query that I want to get results by different order by values.
here is the code.
$strQuery =
"SELECT
category.short_description AS category,
asset.asset_code AS code,
asset_model_number.short_description AS model,
asset_custom_field_helper.cfv_1 AS mnfserial,
asset_custom_field_helper.cfv_6 AS proctype,
asset_custom_field_helper.cfv_7 AS hdd,
asset_custom_field_helper.cfv_8 AS type,
asset_custom_field_helper.cfv_9 AS cond,
asset_custom_field_helper.cfv_10 AS drive,
asset_custom_field_helper.cfv_12 AS os,
asset_custom_field_helper.cfv_13 AS cpu,
asset_custom_field_helper.cfv_14 AS ram,
COUNT(*) AS total
FROM
asset_transaction
LEFT JOIN asset
ON asset_transaction.asset_id = asset.asset_id
LEFT JOIN asset_model
ON asset.asset_model_id = asset_model.asset_model_id
LEFT JOIN asset_model_number
ON asset.asset_model_number_id = asset_model_number.asset_model_number_id
LEFT JOIN asset_custom_field_helper
ON asset.asset_id = asset_custom_field_helper.asset_id
LEFT JOIN user_account
ON asset.created_by = user_account.user_account_id
LEFT JOIN category
ON asset_model.category_id = category.category_id
WHERE asset_transaction.transaction_id = ($txnid)
GROUP BY model";
$objDatabase = QApplication::$Database[1];
// Perform the Query
$objDbResult = $objDatabase->Query($strQuery);
This section I want to get results group by model
echo "<h3>Total Model No<br></h3><strong>";
while ($mixRow = $objDbResult->FetchArray()) {
echo $mixRow['model']. " = " .$mixRow['total'];
echo "<br><strong>";
}
Below section I want the results group by type
echo "<h3>Total Products<br></h3><strong>";
echo "<br>";
while ($row = $objDbResult->FetchArray()) {
echo $row['type']. " = " .$row['total'];
echo "<br><strong>";
I want to avoid writing the sql query each time, instead want to use this query and define my order by value somewhere. How can I do this?

I hope this helps you :)
function getQuery( $order_by_string )
{
return $query = 'Your query .... ORDER BY '.$order_by_string
}
$query = getQuery("something");

You should consider making a query builder class, so you can create queries more freely.
Anyhow, to just set the group by, you can create the function getQueryGroupBy($query,$type) as following:
function getQueryGroupBy($query, $type) {
return $query . 'GROUP BY ' . $type;
}
Your query would be:
$strQuery = "SELECT
category.short_description AS category,
asset.asset_code AS code,
asset_model_number.short_description AS model,
asset_custom_field_helper.cfv_1 AS mnfserial,
asset_custom_field_helper.cfv_6 AS proctype,
asset_custom_field_helper.cfv_7 AS hdd,
asset_custom_field_helper.cfv_8 AS type,
asset_custom_field_helper.cfv_9 AS cond,
asset_custom_field_helper.cfv_10 AS drive,
asset_custom_field_helper.cfv_12 AS os,
asset_custom_field_helper.cfv_13 AS cpu,
asset_custom_field_helper.cfv_14 AS ram,
COUNT(*) AS total
FROM
asset_transaction
LEFT JOIN asset
ON asset_transaction.asset_id = asset.asset_id
LEFT JOIN asset_model
ON asset.asset_model_id = asset_model.asset_model_id
LEFT JOIN asset_model_number
ON asset.asset_model_number_id = asset_model_number.asset_model_number_id
LEFT JOIN asset_custom_field_helper
ON asset.asset_id = asset_custom_field_helper.asset_id
LEFT JOIN user_account
ON asset.created_by = user_account.user_account_id
LEFT JOIN category
ON asset_model.category_id = category.category_id
WHERE
asset_transaction.transaction_id = ($txnid)";
You would then call the function like this:
$query = $this->setGroupBy($strQuery, 'model');
or
$query = $this->setGroupBy($strQuery, 'type');
EDIT
So you would probably end up with this:
$baseQuery =
"SELECT
category.short_description AS category,
asset.asset_code AS code,
asset_model_number.short_description AS model,
asset_custom_field_helper.cfv_1 AS mnfserial,
asset_custom_field_helper.cfv_6 AS proctype,
asset_custom_field_helper.cfv_7 AS hdd,
asset_custom_field_helper.cfv_8 AS type,
asset_custom_field_helper.cfv_9 AS cond,
asset_custom_field_helper.cfv_10 AS drive,
asset_custom_field_helper.cfv_12 AS os,
asset_custom_field_helper.cfv_13 AS cpu,
asset_custom_field_helper.cfv_14 AS ram,
COUNT(*) AS total
FROM
asset_transaction
LEFT JOIN asset
ON asset_transaction.asset_id = asset.asset_id
LEFT JOIN asset_model
ON asset.asset_model_id = asset_model.asset_model_id
LEFT JOIN asset_model_number
ON asset.asset_model_number_id = asset_model_number.asset_model_number_id
LEFT JOIN asset_custom_field_helper
ON asset.asset_id = asset_custom_field_helper.asset_id
LEFT JOIN user_account
ON asset.created_by = user_account.user_account_id
LEFT JOIN category
ON asset_model.category_id = category.category_id
WHERE asset_transaction.transaction_id = ($txnid)";
$objDatabase = QApplication::$Database[1];
// Create the query
$modelQuery = getQueryGroupBy($baseQuery, 'model');
// Perform the Query
$objDbResultByModel = $objDatabase->Query($modelQuery);
echo "<h3>Total Model No<br></h3><strong>";
while ($mixRow = $objDbResultByModel->FetchArray()) {
echo $mixRow['model']. " = " .$mixRow['total'];
echo "<br><strong>";
}
// Create the query
$typeQuery = getQueryGroupBy($baseQuery, 'type');
// Perform the Query
$objDbResultByType = $objDatabase->Query($typeQuery);
echo "<h3>Total Products<br></h3><strong>";
echo "<br>";
while ($row = $objDbResultByType->FetchArray()) {
echo $row['type']. " = " .$row['total'];
echo "<br><strong>";
}
function getQueryGroupBy($query, $type) {
return $query . ' GROUP BY ' . $type;
}

Related

running 2 SQL select statements

I am trying to run 2 SQL Select queries to retrieve data from 2 different tables and then echo the fields from both tables. The code I am trying doesn't seem to work, any help would be appreciated.
$ModelID = $_GET['model_id'];
$result = mysqli_query($con, "SELECT RegNumber, Colour FROM Car WHERE ModelID = '$ModelID'
UNION ALL
SELECT CarModel, CarMake, CostPerDay FROM Model WHERE ModelID = '$ModelID'");
while($row = $result->fetch_assoc())
{
echo $row["CarModel"];
echo $row["CarMake"];
echo $row["CostPerDay"];
echo $row["RegNumber"];
echo " - " .$row["Colour"];
}
You can change request :
SELECT c.RegNumber, c.Colour , m.CarModel, m.CarMake, m.CostPerDay FROM Car c INNER JOIN Model m ON m.ModelID=c.ModelID WHERE c.ModelID = '$ModelID'
try with LEFT JOIN
$result = mysqli_query($con,
"SELECT c.RegNumber, c.Colour, m.CarModel, m.CarMake, m.CostPerDay
FROM Car AS c
LEFT JOIN Model as m ON c.ModelID = m.ModelID
WHERE c.ModelID = '".$ModelID."'"
);

php mysql while loop query optimization

I have php/mysql script running which is like this:
$sql = "select a.column1 from table1 a";
$query = mysql_query($sql);
while ($fec = mysql_fetch_assoc($query)) {
$sub1 = "select column1,column2 from subtable1 where id=" . $fec['a.column1'];
$subquery1 = mysql_query($sub1);
while ($subfec1 = mysql_fetch_assoc($subquery1)) {
//all data .....
}
$sub1 = "select column1,column2 from subtable2 where id=" . $fec['a.column1'];
$subquery2 = mysql_query($sub2);
while ($subfec2 = mysql_fetch_assoc($subquery2)) {
//all data .....
}
$sub2 = "select column1,column2 from subtable3 where id=" . $fec['a.column1'];
$subquery3 = mysql_query($sub3);
while ($subfec3 = mysql_fetch_assoc($subquery3)) {
//all data .....
}
}
Now I've many many many records in table1, subtable1, subtable2 and subtable3. And problem is that it takes around 7 hours to display the results. Moreover the CPU Usage is 100%
Please suggest the optimization tips to overcome this issue.
Use a single query to get all records
SELECT
a.column1,
s.column1,
s.column2,
s2.column1,
s2.column2,
s3.column1,
s3.column2
FROM table1 a
LEFT JOIN subtable1 s ON s.id = a.column1
LEFT JOIN subtable2 s2 ON s.id = a.column1
LEFT JOIN subtable3 s3 ON s.id = a.column1
Here
$sql="
SELECT
a.column1 acolumn1,
s.column1 scolumn1,
s.column2 scolumn2,
s2.column1 s2column1,
s2.column2 s2column2,
s3.column1 s3column1,
s3.column2 s3column2
FROM table1 a
LEFT JOIN subtable1 s ON s.id = a.column1
LEFT JOIN subtable2 s2 ON s.id = a.column1
LEFT JOIN subtable3 s3 ON s.id = a.column1";
$query=mysql_query($sql);
while ($fec=mysql_fetch_assoc($query)) {
// display any info here
}
Use aliases for accessing different table columns

How to write MySQL aliases properly?

For all those that care, I found that I needed to re read the basics on querying. Once sorted, I realised I had a fair few errors throughout my code.
I've got a query I'm trying to build and I'm throwing up error after error regarding to ambiguity. Would anyone kindly show me how to execute MySQL aliases properly?
This is my code so far. It worked fine until I put the join in there. I suspect it's because I'm referencing 'wine' more than once in the same query, but that may be one of many problems.
$query =
"SELECT
wine_id,
wine_name,
winery_name,
region_name,
year,
variety
FROM
wine AS w,
winery,
region,
grape_variety
JOIN
wine
ON
grape_variety.variety_id = wine.wine_id
JOIN
wine_variety
ON
wine.wine_id = wine_variety.variety_id
WHERE
winery.region_id = region.region_id
AND
wine.winery_id = winery.winery_id";
if (!empty($wineName)) {
$query .= " AND wine_name = '{$wineName}'";
}
if (!empty($wineryName)) {
$query .= " AND winery_name = '{$wineryName}'";
}
// If the user has specified a region, add the regionName
// as an AND clause
if (isset($regionName) && $regionName != "All") {
$query .= " AND region_name = '{$regionName}'";
}
// If the user has specified a variety, add the grapeVariety
// as an AND clause
if (isset($grapeVariety) && $grapeVariety != "Riesling") {
$query .= " AND variety = '{$grapeVariety}'";
}
Try to do it this way:
SELECT w.wine_id, w.wine_name, winery_name, region_name, year, variety
FROM
wine AS w
join winery on w.winery_id = winery.winery_id
join region on winery.region_id = region.region_id,
join grape_variety on grape_variety.variety_id = w.wine_id
Your query must be like:
SELECT
w.wine_id,
w.wine_name,
wy.winery_name,-- I assume this column from table `wy`
r.region_name, -- column from table `region`
w.year,
w.variety
FROM wine w
INNER JOIN winery wy ON (wy.winery_id = w.winery_id )
INNER JOIN region r ON ( r.region_id = wy.region_id )
INNER JOIN grape_variety gv ON (gv.variety_id = w.wine_id)
INNER JOIN wine_variety wv ON (wv.variety_id = w.wine_id)
...
append other WHERE conditions here
Note: if you give table structure then it would be more clear, at first I assume whatever column you retrieve is from main table and
if all tables in query have same column name then use table_alias_name.column_name.
try this
SELECT
w.wine_id,
w.wine_name,
wy.winery_name,
r.region_name,
r.year,
wv.variety
FROM wine w
INNER JOIN winery wy ON (wy.winery_id = w.winery_id )
INNER JOIN region r ON ( r.region_id = wy.region_id )
INNER JOIN grape_variety gv ON (gv.variety_id = w.wine_id)
INNER JOIN wine_variety wv ON (wv.variety_id = w.wine_id)
Use This one
$query =
"SELECT
w.wine_id,
w.wine_name,
winery.winery_name,
region.region_name,
year,
grape_variety.variety
FROM
wine AS w,
winery,
region,
grape_variety
JOIN
wine
ON
grape_variety.variety_id = wine.wine_id
JOIN
wine_variety
ON
wine.wine_id = wine_variety.variety_id
WHERE
winery.region_id = region.region_id
AND
wine.winery_id = winery.winery_id";
if (!empty($wineName)) {
$query .= " AND w.wine_name = '{$wineName}'";
}
if (!empty($wineryName)) {
$query .= " AND winery.winery_name = '{$wineryName}'";
}
// If the user has specified a region, add the regionName
// as an AND clause
if (isset($regionName) && $regionName != "All") {
$query .= " AND region.region_name = '{$regionName}'";
}
// If the user has specified a variety, add the grapeVariety
// as an AND clause
if (isset($grapeVariety) && $grapeVariety != "Riesling") {
$query .= " AND grape_variety.variety = '{$grapeVariety}'";
}

php foreach in foreach in foreach

This is a hypothetical question. If I have 3 arrays from 3 separate sql db queries that all relate to another. For example...
//db
schools
id | school_name
classes
id | class_name | school_id
students
id | student_name | class_id
And I want to display everything in a huge list like this...
//php
foreach(schools as school){
echo '<h1>' . $school->school_name . '<h1>';
foreach(classes as class){
if($class->school_id == $school->id){
echo '<h2>' . $class->class_name . '<h2>';
foreach(students as student){
if($student->class_id == $class->id){
echo '<h3>' . $student->student_name . '<h3>';
}
}
}
}
}
I have to make 3 database calls. Is there a way to grab all this information in a single db query? Like maybe an array in an array in an array and then somehow loop through? Or is this the best way to do this?
You can do a join which will allow you to have 1 for each. Are you wanting everything or any sort of filter ?
You can join those table, to get one big array with flattened data. When looping through this data, you can check if the id of the previous record still matches the id of the current record. If not, you can output a new header. It is important, though, that the resultset is properly sorted for this.
SELECT
s.id AS school_id,
s.school_name,
c.id AS class_id,
c.class_name,
st.id AS student_id,
st.student_name
FROM
schools s
INNER JOIN classes c ON c.school_id = s.id
INNER JOIN students st ON st.class_id = c.id
ORDER BY
s.id,
c.id,
st.id
If you have it all in a flattened structure, you can even make it into a nested array structure again something like this:
foreach ($resultset as $row)
{
$schools[$row->school_id]->school_name =
$row->school_name;
$schools[$row->school_id]->classes[$row->class_id]->class_name =
$row->class_name;
$schools[$row->school_id]->classes[$row->class_id]->students[$row->student_id]->student_name =
$row->student_name;
}
var_dump($schools);
After that, you can still use the nested for loops to process the array, but it will be in a more efficient way, since the data is already sorted out: classes are already added to the school they belong to, and student are already added to the right class.
<?php
try {
$pdo = new PDO("mysql:host=127.0.0.1;dbname=school", "username");
} catch (PDOException $e) {
echo "PDO Connection failed: " . $e->getMessage();
exit(1);
}
$sql = <<<SQL
SELECT schools.school_name, classes.class_name, students.student_name
FROM
schools INNER JOIN classes ON (schools.id = classes.school_id)
INNER JOIN students ON (classes.id = students.class_id)
ORDER BY 1, 2;
SQL;
$result = $pdo->query($sql);
if ($result == false) {
die("query failed?!");
}
$school = "";
$class = "";
while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
if ($school != $row['school_name']) {
$school = $row['school_name'];
echo "\nSchool: $school\n\n";
}
if ($class != $row['class_name']) {
$class = $row['class_name'];
echo " Class: $class\n\n";
echo " Student list:\n";
}
echo " {$row['student_name']}\n";
}
$res = mysql_query('SELECT school_name, class_name, student_name, sc.id AS scid, c.id AS cid, st.id AS stid FROM schools sc LEFT JOIN classes c ON (sc.id = c.school_id) LEFT JOIN students st ON (c.id = st.class_id) ');
$arr = array();
while ($v = mysql_fetch_assoc($res)) {
$arr[$v['school_name']][$v['class_name']][$v['stid']] = $v['student_name'];
}
print_r($arr);
You could do it all in one SQL query that might look something like:
SELECT schools.schoolname, classes.class_name, students.student_name
FROM
schools INNER JOIN classes ON (schools.id = classes.school_id)
INNER JOIN students ON (classes.id = students.class_id)
ORDER BY 1, 2;
Then you could walk the result set in one loop, but you'd probably want to add some logic to only display the school name and class name once for each time it changes.

Join MySQL Table then filter result as column name

here is my code i am using to fetch mysql result from 4 different tables
SELECT DISTINCT c.title as CourseTitle, t.title as TopicTitle, l.title as LessonTitle, r.title as ResourceTitle, r.location, r.type, r.duration
FROM j17_lessons l, j17_topics t, j17_courses c, j17_resources r
WHERE
CONCAT(c.title, t.title, l.title, r.title, r.type, r.location) LIKE '%Fatih%'
AND c.id = t.course_id
AND l.topic_id = t.id
AND r.lesson_id = l.id
ORDER BY c.title, t.id, l.id, r.id;
Here is screen shot of my fetch result
http://i40.tinypic.com/2v1w0ib.png
Now what i need is to create a HTML Tables for each 'CourseTitle' in database.
Using SQL statement and PHP Code i can get result for first query but i need a second query to split table foreach 'CourseTitle'
/* connect to the db */
$connection = mysql_connect('localhost','root','123');
mysql_select_db('alhudapk',$connection);
/* show tables */
$result = mysql_query('SELECT DISTINCT c.title as CourseTitle, t.title as TopicTitle, l.title as LessonTitle, r.title as ResourceTitle, r.location, r.type, r.duration
FROM j17_lessons l, j17_topics t, j17_courses c, j17_resources r
WHERE
CONCAT(c.title, t.title, l.title, r.title, r.type, r.location) LIKE '%Taleem%'
AND c.id = t.course_id
AND l.topic_id = t.id
AND r.lesson_id = l.id
ORDER BY c.title, t.id, l.id, r.id',$connection) or die('cannot show tables');
while($tableName = mysql_fetch_row($result)) {
$table = $tableName[0];
echo '<h3>',$table,'</h3>';
$result2 = mysql_query('SELECT '.$table . 'AS' .$table);
if(mysql_num_rows($result2)) {
Please guide me to build a correct and better code
What I would do is put the database results into a big array structure with the data arranged in the same sort of order it should be printed out. This makes maintaining the code a bit easier.
// run the query as you did in the question
$courses = array();
// use mysql_fetch_assoc as it makes the code clearer
while($row = mysql_fetch_assoc($result)) {
$ct = $row['CourseTitle'];
// Found a new Course Title? If so create an array to put the data rows in
if(!isset($courses[$ct]))
$courses[$ct] = array();
// add this row to the end of its course array
$courses[$ct][] = $row;
}
// now print the results out
foreach($courses as $title =>$course) {
echo "<h3>$title</h3>";
echo "<table>";
foreach($course as $line) {
echo "<tr><td>" . $line['TopicTitle'] . "</td><td>"
. $line['LessonTitle'] . "</td></tr>";
echo "</table>";
}
The code above is only printing out the first 2 columns
, but if you can get it to work you should be able to add the rest quite easily.
add:
GROUP BY c.title
to the end of your SQL statement.

Categories