A better way to display this data from MySql using php - php

I currently have data like this in a table:
id | type
------------
1 | 1
2 | 1
3 | 2
4 | 2
5 | 3
6 | 3
6 | 3
I need to display data like this:
Type 1
--All type ones go here
Type 2
-- All type twos go here
Type 3
All type threes go here
The way I do it right now is by using two separate sql statements and loops.
select distinct type as type from table
while()
{
select type from table where type = type;
while()
{
}
}
Is there a better way to do this and get the results I want, or is using two loops the only way?

Change your query so that you are using ORDER BY type ASC.
Loop through the results, build an associative array where the key is the type, and the values are the ids.
Now you only have one loop, and ids can be accessed by their type from the associative array. It should be trivial to loop through the array by the key, and then show all the ids for that key.

Just select everything, and check whenever you hit a new type. This allows you to list everything out in O(n) time using only one query.
$result = mysql_query('SELECT id, type FROM table ORDER BY type ASC');
$type = 0;
while ($row = mysql_fetch_assoc($result) {
if ($type != $row['type']) {
// New type found
$type = $row['type'];
echo "Type " + $row['type'] + "\n";
}
echo "-- " + $row['id'] + "\n";
}
This would give you an output like this
Type 1
-- 1
-- 2
Type 2
-- 3
-- 4
Type 3
-- 5
-- 6
-- 7

Use GROUP_CONCAT() with GROUP BY:
SELECT
`type`,
GROUP_CONCAT(`id` SEPARATOR ',') as `ids`
FROM
`table`
GROUP BY
`type`
ORDER BY
`type`;
In each cycle iteration, $row['ids'] might be explode()d, like:
<?php
while($row = $result->fetch_assoc()){
$ids = explode(',', $row['ids']);
echo 'Type ', $row['type'], PHP_EOL;
if(empty($ids))continue;
foreach($ids as $id){
echo $id, ' ';
}
echo PHP_EOL;
}
?>

Related

Fetch current and next row and compare in a loop

I would like to compare two values from a table:
This is my table:
ID;VALUE
1;700
2;600
3;800
4;900
This is my query:
$stmt = $db->query("SELECT ID, VALUE FROM TABLE);
Now i like to compare the result of the current row with the next row. In mysql it was easy beacause i have to set the row number. I did not find any solution with PDO.
This is my code yet:
while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$id = $row["ID"];
$val_current = $row["VALUE"];
$row_next = $stmt->fetch(PDO::FETCH_ASSOC);
$val_next = $row["VALUE"];
if ($val_current > $val_next){
echo "$id is greate!";
}else{
echo "$id is less!";
}
}
The Result is:
1 is greater
3 is less
He missed to check the ID 2 agains ID 3 becaue i fetch the next element in the while loop. So i fetch it to get the next value and i fetch again in the loop. Can i reposition the cursor at the end of the loop?
If you are running MySQL 8.0, this is straight-forward with window function lead():
select
t.*,
(value - lead(value) over(order by id) > 0) is_greater
from mytable t
This gives you a boolean flag called is_greater, with following possible values:
1: this value is greater than the next one
0: this value is smaller than the next one
null: there is no next value
Demo on DB Fiddle:
ID | VALUE | is_greater
-: | ----: | ---------:
1 | 700 | 1
2 | 600 | 0
3 | 800 | 0
4 | 900 | null
In earlier versions, one option is to use a correlated subquery:
select
t.*,
(value - (
select t1.value
from mytable t1
where t1.id > t.id
order by t1.id limit 1
) > 0) is_greater
from mytable t
You just need to remember the previous row and use it in the next iteration pretending it's the current one, whereas the current row will serve as the next one.
$row = null;
while($row_next = $stmt->fetch(PDO::FETCH_ASSOC)) {
if ($row !== null)) {
$id = $row["ID"];
$val_current = $row["VALUE"];
$val_next = $row_next["VALUE"];
if ($val_current > $val_next){
echo "$id is greater!";
}else{
echo "$id is less!";
}
echo "\n";
}
$row = $row_next;
}

How to add not existing record and return it with zero value in Mysqli

QUERY:
SELECT month(date_created), count(a.ticket_num)
FROM ticket as a
LEFT JOIN user_management as b on b.engineer_id = a.ticket_engineer
WHERE b.tl_id = 'sample_id'
AND year(date_created) = '2019'
GROUP BY extract(year from date_created), extract(month from date_created)
SAMPLE OUTPUT:
month | ticket_num
----------------------
2 | 12
4 | 24
6 | 78
EXPECTED SAMPLE OUTPUT:
month | ticket_num
----------------------
1 | 0
2 | 12
3 | 0
4 | 24
5 | 0
6 | 78
As you can see the above expected output, i'm trying to place all existing month in the first column and set all the count to zero if not existed in the second column. As of now, i only have the query for sorting the ticket count by month that is existed when the ticket is created.
There are different approaches to this problem. One is pure SQL for example.
But I would say a PHP based solution is simpler. Basically you need to get your data into array, then create a loop that outputs the desired months order, and have a condition that sees whether we have a corresponding row in our array and outputs ether the actual data or a zero accordingly.
The only tricky part is to have such an array that would let us check the data availability. For this we have to index it with month numbers. Not a big deal actually
$sql = "SELECT month(date_created), count(a.ticket_num) ...";
$res = $mysqli($sql);
$data = [];
while($row = mysqli_fetch_row($res)) {
$data[$row[0]] = $row[1];
}
Now $data is an array indexed by the month number. The rest is a primitive loop
foreach (range(1,12) as $month) {
echo $data[$month] ?: 0;
}
On a side note I would like to advertise using PDO as opposed to mysqli for your database interactions as this case clearly displays the superiority of the former. Using PDO we can get the indexed array right away, without an explicit loop, thanks to a special fetch mode:
$sql = "SELECT month(date_created), count(a.ticket_num) ...";
$data = $data = $pdo->query($sql)->fetchAll(PDO::FETCH_KEY_PAIR);
That's all!

MYSQL: List all column names where their values = "Yes"

I have a table like so:
User_Id Column1 Column2 Column3
1 Yes No Yes
2
I want to use mysql query to list all the column names (there are more than 3) which match the User_Id '1' and have a value of 'Yes'.
I get an error:
Trying to get property 'num_rows' of non-object
Here is what I have tried:
<?php $myStats = $mysqli->query("SELECT COLUMN_NAME FROM user_services.columns WHERE myColumn = 'Yes'");
if ($myStats->num_rows > 0) {
// output data of each row
while($row = $myStats->fetch_assoc()) {
$rows[] = $row; }
return $rows; ?>
Please can someone show me where I am going wrong?
Thanks in advance.
The CONCAT_WS function comes in handy here:
SELECT CONCAT_WS(',', IF(Column1='Yes', 'Column1', NULL),
IF(Column2='Yes', 'Column2', NULL),
IF(Column3='Yes', 'Column3', NULL)) AS columns
FROM user_services.columns
WHERE User_Id = 1;
If you have more than 3 columns, then you may add more terms to above CONCAT_WS call. Your problem mainly seems to be a SQL one, so I won't add any PHP code.
Note that your design might be better off if your column strings were spread across rows, rather than columns. For instance, consider the following alternative:
User_Id | number | val
1 | 1 | Yes
1 | 2 | No
1 | 3 | Yes
Then, if you wanted all column numbers which were yes for user 1, you could simply do:
SELECT
User_Id,
GROUP_CONCAT(number ORDER BY number) columns
FROM yourTable
WHERE
User_Id = 1
GROUP BY
User_Id;

update whole column with an array input from top to bottom without id info using prepared statements

I have 2 tables for my articles in DB:
articles
tags
tags table structure and current state:
primary key for my tags table is tag column.
tag | post_ids | count |
-------------------------------------
a | 2,0 | |
b | 1,2,0,0 | |
tag1 | 1,2,0,0 | |
j | 2,0 | |
I want to update count column after any INSERT (new post) or UPDATE (existing post) action and I want to do it with prepared statements.
For the time being, I can dynamically construct the input: $array = array("2","4","4","2") which is the related values of the count column to be updated.
And with the code below; I tried to update the count column however count always updates with value = 2 for all count rows.
I have no warning/error.
MySQL version: 5.5
I have to update 1st count row with the $array[0], 2nd count row with the $array[1] ... So I have to utilize LIMIT, OFFSET arguments
I learnt that MySQL doesn't allow OFFSET in UPDATE queries
I am not capable to write complex queries, I searched SO and found the Q&A: LIMIT offset or OFFSET in an UPDATE SQL query
It seemed to me the sql I used from that Q&A is logically suitable for my case however I didn't understand the sql.
I am not 100% sure that problematic area is the sql.
I want to correct my code and learn why it fails?
Can you please help?
Best regards
MY CODE
$query = "UPDATE tags SET count = ?
WHERE tag IN(SELECT tag FROM (SELECT tag FROM tags LIMIT ?,1) as u)";
$stmt = $mysqli->prepare($query);
if($stmt === false)
{
trigger_error('SQL Error: ' . $mysqli->error, E_USER_ERROR);
}
$stmt->bind_param("ii", $count, $i);
$i = 0;
foreach ($array as $a) // $array: related values of the `count` column to be updated
{
$count = intval($a);
$stmt->execute();
$i = $i + 1;
}
$stmt->close();

Retrieve total amounts of rows containing strings

I have a table in MySQL, with 5(sort of) possible values in the column 'type'... I say sort of because the data type is 'set' and 1 type has a subcategory... It's for a type of property, so the possible types are retail, office, hospitality, industrial, residential(multi family), residential(single family).
I'm attempting to paginate the results and I need to know how many pages each should have. So I need a query that tells me how many of each type are in the table, the user can select residential as a category, or single, multi as subcategories.
I can't figure out how to do a query that tells me how many of each there are, or how to retrieve those numbers as variables I can use to divide be items per page.
id | type
-----------------------
1 | office
2 | residential,single
3 | industrial
4 | residential,multi
5 | retail
6 | office
7 | hospitality
8 | residential,single
etc....
so if this was the data, I would need to get:
$office = 2
$residential = 3
$industrial = 1
$single = 2
etc...
Use array_count_values() function
Check the link http://php.net/manual/en/function.array-count-values.php
From their website http://php.net/manual/en/function.array-count-values.php;
and Try this code
<?php
$query= // Run your select query.
$result= mysqli_query($link, $query);
//Run the while loop
while($row= mysqli_fetch_array($result))
{
$array[]=$row['Column_Name'];//Store the result in array
}
$count = array_count_values($array);//Use array count
print_r($count);//See the result
Or if you see The out put the way you want
Run Foreach loop on the $count array
foreach($count as $key => $value) {
//Get the out put From new array
echo $value .' '. $key.'<br/>' ;
}
A count and group by should do the trick;
SELECT id, type, COUNT(*) as count
FROM mytable
GROUP By id

Categories