make a multidimensional array php mysql - php

I link my last question to explain that i need
obtain results of two different tables mysql
This is the result of my mysql query.
date | rate | percent
2017-01-06 500 0
2017-01-07 500 0.10
2017-01-07 500 0.15
How can i make this array, i am tring with php but i canĀ“t do this, i can do it with one dimension array, but no a multidimensional array like this
Array
(
[1] => Array
(
[0] => Array
(
[date] => 2017-01-06
[rate]=>500
[percent] => 0.00
)
[1] => Array
(
[date] => 2017-01-07
[rate]=>500
[percent] => 0.10
)
[2] => Array
(
[0] => Array
(
[date] => 2017-01-06
[rate]=>500
[percent] => 0.00
)
[1] => Array
(
[date] => 2017-01-07
[rate]=>500
[percent] => 0.15
)
)
)

It is a matter of (if I understand the problem) plucking the MAX() and MIN() percent values for each date. For this, you must use GROUP BY.
SELECT s.date, s.rate, MAX(p.percent) AS maxperc, MIN(p.percent) AS minperc
FROM stock s
LEFT JOIN promotions p ON s.date = p.date
WHERE s.date BETWEEN '2017-01-29' AND '2017-01-31'
GROUP BY s.date,s.rate;
...I haven't test that, so it may need some fiddling with.
Then as you loop through your result set, you can declare the two separate subarrays and build your complete array.
$array=[];
$i=0;
while($row=mysqli_fetch_assoc($result)){
$array[0][$i]["date"]=$row["date"];
$array[0][$i]["rate"]=$row["rate"];
$array[0][$i]["perc"]=$row["minperc"];
$array[1][$i]["date"]=$row["date"];
$array[1][$i]["rate"]=$row["rate"];
$array[1][$i]["perc"]=$row["maxperc"];
++$i;
}
By this point, I've made too many assumptions about your purpose/usage.
Basically, set zero as the percent default, query for highest and lowest percent for each date-rate pair (if zero, then zero will appear as highest and lowest value). Do whatever you wish with the result set.

Related

Streamlining array to get total for each key

I'm trying to build arrays based off of two queries, one in mysql one on db2. I've built the main arrays, the first dealing with product info and the 2nd dealing with customer info but they have some values in common.
This is working as far as structure but I've been trying to build a final array to contain data from the initial arrays that will build a report.
For now, I'm just going to try and output a report or csv file for each sku_id from the first query, and the total number/ quantity from the 2nd query.
The 2nd query/array contain multiple attributes on a per product/customer basis.
(
[1] => 2
)
Array
(
[1] => 5
)
Array
(
[1] => 14
)
Basically, I pulled three records from the first table for sku_id '1' and matched those three records in db2 for the same sku. Each element corresponds to a customer, so this structure says "customer A had 2 of sku_id 1, customer B had 5 of sku_id 1 and customer C had 14 of sku_id 1'
For the purpose of the report, each line will be for each sku so I want to instead output this as:
array
(
[1] => 21
)
Showing that overall, sku_id 1 had a total of 21. So I still want to keep my initial arrays structured like they are, but I want to modify my final array to just give me line items for the report.
How can I do that?
$skuQuery = "
SELECT
sku_id,
dealer_id,
locations,
s.sku_group_id as groupID,
s.frame as frame,
s.cover1 as cover,
s.color1 as color,
start_date - interval 7 day as start_date
from products p
inner join skus s on p.sku_id = s.id
where curdate() between p.start_date and p.expire_date
group by sku_id, dealer_id
limit 3";
$skuRslt = mysqli_query($conn,$skuQuery);
while($skuRow = mysqli_fetch_assoc($skuRslt)){
$skuResult['sku_id'] = $skuRow;
$dealerQuery = "
SELECT
cstnoc,
sum(orqtyc) as TotalQTY
from table
where cstnoc = {$skuRow['dealer_id']}
AND framec = {$skuRow['frame']}
AND colr1c = {$skuRow['color']}
AND covr1c = {$skuRow['cover']}
AND extd2d >= " . str_replace('-', '', $skuRow['start_date']) . "
group by cstnoc, framec
";
$dealerRslt = odbc_exec($DB2Conn, $dealerQuery);
$dealerResult = [];
foreach($skuResult as $skuRow){
while($dealerRow = odbc_fetch_array($dealerRslt)){
if ( !isset($dealerResult[$dealerRow['CSTNOC']]) ) {
$dealerResult[$dealerRow['CSTNOC']] = 0;
}
$dealerResult[$dealerRow['CSTNOC']] += $dealerRow['TOTALQTY'];
}
}
$skuTots = array_fill_keys(array_unique(array_column($skuResult, 'sku_id')), 0);
foreach ($skuResult as $rec) {
$skuTots[$rec['sku_id']] += $dealerResult[$rec['dealer_id']];
}
print_r($skuTots);
}
UPDATE:
This is the print out for my first two arrays:
Array
(
[0] => Array
(
[sku_id] => 1
[dealer_id] => 1976
[locations] => 1
[groupID] => 1
[frame] => 1051
[cover] => 1150
[color] => 99
[start_date] => 2018-03-
)
[1] => Array
(
[sku_id] => 1
[dealer_id] => 5400
[locations] => 1
[groupID] => 1
[frame] => 1051
[cover] => 1150
[color] => 99
[start_date] => 2017-04-
)
[2] => Array
(
[sku_id] => 1
[dealer_id] => 11316
[locations] => 1
[groupID] => 1
[frame] => 1051
[cover] => 1150
[color] => 99
[start_date] => 2017-02-
)
)
Array
(
[0] => Array
(
[CSTNOC] => 1976
[TOTALQTY] => 2
)
[1] => Array
(
[CSTNOC] => 5400
[TOTALQTY] => 5
)
[2] => Array
(
[CSTNOC] => 11316
[TOTALQTY] => 14
)
)
And here is an example of my end result I'm trying to achieve:
In the below example, sku_id, groupID and location would come directly from the first query. Days is the number of days between start_date (from query 1) and curDate(). Qty is orqtyc from query 2 and Average is a calculation based on locations, days and qty. Each row is based on a different customer, so even though the below example is for one sku, the rows signify a different customer with different locations, qty, etc.
SKU_id | groupID | locations (n) | Days (x) | Qty(q) | Average (x/(q/n))
--------------------------------------------------------------------------------
123 1 3 120 15 24
123 1 2 12 6 4
The Report or CSV would then only show one line item for the above:
SKU | Group | Average Days | Total units sold
123 | 1 | 28 | 21
Basically, for every sku I'm getting those records and then I need to do those calculations by row, and get a total of those values for each sku. The report will only have one line item per sku.

multidimensional array query mysql

I am working in a hotel reservation system, and the rates are per night.
My database has two tables, one called stock and the other promotions. The first contain one row for day (365 days), and the last one only the days that have a percent of discount. Sometimes, some days have two or more different percent of discount. In this case 30 and 31 of january have 0.10 and 0.15.
Table stock
date | rate
--------------------------
2017-01-29 500
2017-01-30 500
2017-01-31 500
Table promotions
date | percent
--------------------------
2017-01-30 0.10
2017-01-31 0.10
2017-01-30 0.15
2017-01-31 0.15
while a mysql query (SELECT s.date, s.rate, IFNULL(p.percent, 0)
FROM stock s LEFT JOIN promotions p ON s.date = p.date
WHERE s.date as date BETWEEN '2017-01-29' AND '2017-01-31') i obtain this result:
date | rate | percent
-----------------------------------
2017-01-29 500 0
2017-01-30 500 0.10
2017-01-31 500 0.10
2017-01-30 500 0.15
2017-01-31 500 0.15
i need to create a multidimensional array, that contain one array for each percent of discount, and these arrays contain the three days, the day 29 with a percent 0.00 and the other two days 0.10. a new one the day 29 with a percent 0.00 and the other two days 0.15. i am tring but i cant assign the day 29 in both arrays.
Array
(
[1] => Array
(
[0] => Array
(
[date] => 2017-01-29
[rate]=>500
[percent] => 0.00
)
[1] => Array
(
[date] => 2017-01-30
[rate]=>500
[percent] => 0.10
)
[2] => Array
(
[date] => 2017-01-31
[rate]=>500
[percent] => 0.10
)
)
[2] => Array
(
[0] => Array
(
[date] => 2017-01-29
[rate]=>500
[percent] => 0.00
)
[1] => Array
(
[date] => 2017-01-30
[rate]=>500
[percent] => 0.15
)
[2] => Array
(
[date] => 2017-01-31
[rate]=>500
[percent] => 0.15
)
)
)
At its core, this feels like a database problem.
Set the percent column as NOT NULL and set 0 as the DEFAULT.
ALTER TABLE promotions CHANGE COLUMN percent [maintain-its-type] NOT NULL DEFAULT '0';
Then it is a matter of (if I understand the problem) plucking the MAX() and MIN() percent values for each date.
SELECT s.date, s.rate, MAX(p.percent) AS maxperc, MIN(p.percent) AS minperc
FROM stock s
LEFT JOIN promotions p ON s.date = p.date
WHERE s.date BETWEEN '2017-01-29' AND '2017-01-31'
GROUP BY s.date,s.rate;
...I haven't test that, so it may need some fiddling with.
Then as you loop through your result set, you can declare the two separate subarrays and build your complete array.
$array=[];
$i=0;
while($row=mysqli_fetch_assoc($result)){
$array[0][$i]["date"]=$row["date"];
$array[0][$i]["rate"]=$row["rate"];
$array[0][$i]["perc"]=$row["minperc"];
$array[1][$i]["date"]=$row["date"];
$array[1][$i]["rate"]=$row["rate"];
$array[1][$i]["perc"]=$row["maxperc"];
++$i;
}
By this point, I've made too many assumptions about your purpose/usage.
Basically, set zero as the percent default, query for highest and lowest percent for each date-rate pair (if zero, then zero will appear as highest and lowest value). Do whatever you wish with the result set.

php mysql check if vendor has 3 low consecutive ratings

on my ratings table for my software i have 4 fields.
id autoincrement
rvid vendor id
ratedate date of rating
rating the actual numeric rating
I have done alot with it over the last few months but this time im stumped and i cant get a clear picture in my head of the best way to do this. What i am trying to do is find out if the vendor has had 3 low 'consecutive' ratings. If their last three ratings have been < 3 then i want to flag them.
I have been playing with this for a few hours now so i thought i would ask (not for the answer) but for some path direction just to push me forward, im stuck in thought going in circles here.
I have tried GROUP BY and several ORDER BY but those attempts did not go well and so i am wondering if this is not a mysql answer but a php answer. In other words maybe i just need to take what i have so far and just move to the php side of things via usort and the like and do it that way.
Here is what i have so far i did select id as well at first thinking that was the best way to get the last consective but then i had a small breakthrough that if they have had 3 in a row the id does not matter, so i took it out of the query.
$sql = "SELECT `rvid`, `rating` FROM `vendor_ratings_archive` WHERE `rating` <= '3' ORDER BY `rvid` DESC";
which give me this
Array
(
[0] => Array
(
[rvid] => 7
[rating] => 2
)
[1] => Array
(
[rvid] => 5
[rating] => 1
)
[2] => Array
(
[rvid] => 5
[rating] => 0
)
[3] => Array
(
[rvid] => 5
[rating] => 3
)
)
this is just just samples i tossed in the fields, and there are only 4 rows here where as in live it will be tons of rows. But basically this tells me that these are the vendors that have low ratings in the table. And that is where i get stumpted. I can only do one sort in the query so that is why i am thinking that i need to take this and move to the php side to finish it off.
I think i need to sort the elements by rvid with php first i think, and then see if three elements in a row are the same vender (rvid).
Hope that makes sense. My brain hurts lol...
update - here is all of the table data using *
Array
(
[0] => Array
(
[id] => 7
[rvid] => 7
[ratedate] => 2016-05-01
[rating] => 2
)
[1] => Array
(
[id] => 8
[rvid] => 5
[ratedate] => 2016-05-01
[rating] => 1
)
[2] => Array
(
[id] => 6
[rvid] => 5
[ratedate] => 2016-05-01
[rating] => 0
)
[3] => Array
(
[id] => 5
[rvid] => 5
[ratedate] => 2016-05-01
[rating] => 3
)
)
Here's one way you can begin approaching this - completely in SQL:
Get the last rating for the vendor. ORDER BY date DESC, limit 1.
Get the second to last rating for the vendor. ORDER BY date DESC, limit 1, OFFSET 1.
Then write a query that does a LEFT join of the first two tables. You will have a dataset that has three columns:
vendor id
last rating
second to last rating
Then you can write an expression that says "if column1 is <3 and column2 < 3, then this new column is true"
You should be able to extend this to three columns relatively easily.
Here is what a came up with to solve this riddle. I think explaining it on here helped as well as Alex also helped as he keyed my brain on using the date. I first started looking at using if statment inside of the query and actually that got my brain out of the box and then it hit me what to do.
It is not perfect and certainly could use some trimming to reduce the code, but i understand it and it seems to work, so that is par for me on this course.
the query...
$sql = "SELECT `rvid`, `ratedate`,`rating` FROM `vendor_ratings_archive` WHERE `rating` <= '3' ORDER BY `ratedate`, `rvid` DESC";
which gives me this
Array
(
[0] => Array
(
[rvid] => 7
[ratedate] => 2016-05-01
[rating] => 2
)
[1] => Array
(
[rvid] => 5
[ratedate] => 2016-05-01
[rating] => 1
)
[2] => Array
(
[rvid] => 5
[ratedate] => 2016-05-01
[rating] => 0
)
[3] => Array
(
[rvid] => 5
[ratedate] => 2016-05-01
[rating] => 3
)
)
notice how vendor (rvid) 5 is grouped together which is an added plus.
next a simple foreach to load a new array
foreach($results as $yield)
{
$rvidarray[] = $yield['rvid'];
}//close foreach
which gives me this
Array
(
[0] => 7
[1] => 5
[2] => 5
[3] => 5
)
then we count the array values to group dups
$rvidcounter = array_count_values($rvidarray);
which results in this
Array(
[7] => 1
[5] => 3
)
so now vender 7 as 1 low score and vendor 5 has 3 low scores and since they were already sorted by date i know that its consecutive. Well it sounds good anyway lol ")
then we create our final array with another foreach
foreach($rvidcounter as $key => $value)
{
//anything 3 or over is your watchlist
if($value > 2)
{
$watchlist[] = $key; //rvid number stored
}
}//close foreach
which gives me this
Array
(
[0] => 5
)
this was all done in a service function. So the final deal is everyone in this array has over 3 consecutive low ratings and then i just use a returned array back in my normal php process file and grab the name of each vender by id and pass that to the html and print out the list.
done...
please feel free to improve on this if you like. I may or may not use it because the above code makes sense to me. Something more complicated may not make sense to me 6 mos from now lol But it would be interesting to see what someone comes up with to shorten the process a bit.
Thanks so much and Happy Coding !!!!!
Dave :)
You could do it in SQL like that:
SET #rvid = -1;
SELECT DISTINCT rvid FROM
(
SELECT
rvid,
#neg := rating<3, /* 0 or 1 for addition in next line */
#count := IF(#rvid <> rvid , #neg, #count+#neg) AS `count`, /* set or add */
#rvid := rvid /* remember last row */
FROM
testdb.venrate
ORDER BY
rvid, datetime desc
) subq
WHERE count>=3
;
You set a variable to a non existing id. In each chronologically sorted row you check if rating is too low, that results in 1 (too low) or 0 (ok). If rvid is not equal to the last rvid, it means a new vender section is beginning. On begin of section set the value 0 or 1, else add this value. Finally store the current row's rvid for comparison in next row process.
The code above is looking for 3 consecutive low ratings (low means a value less than 3) over all the time.
A small modification checks if all the latest 3 ratings has been equal to or less than 3:
SET #rvid = -1;
SELECT DISTINCT
rvid
FROM
(
SELECT
rvid,
#high_found := rating>3 OR (#rvid = rvid AND #high_found) unflag,
#count := IF(#rvid <> rvid , 1, #count+1) AS `count`,
#rvid := rvid /* remember last row */
FROM
testdb.venrate
ORDER BY
rvid, datetime desc
) subq
WHERE count=3 AND NOT unflag
;

Get the highest value of array query mysql, php

With a big Thanks to others here i get this query now. its working fine, but i would need to get just the highest value of the post_id (how_many). it seems not possible to set a MAX(count(*)) on that. so how could i change this to get only the highest count by every id? i just need the value of every id where count == highest. how could i do this? thanks for any help.
$test = $wpdb->get_results('select
posts_id, value,count(*) as how_many
From wp_mrp_rating_item_entry_value
group by
posts_id, value
order by count(*) desc');
echo '<pre>';
print_r($test);
echo '</pre>';
i would need something like order by MAX((count(*)) or MAX((count(how_many))
i already read this but i dont know how to use this for my purpose Filtering log file using COUNT, GROUP BY, ORDER BY MAX
this is an example of the output i get now. so number 1 should not appear because number [0] has been voted 2 times. (how_many). i just need every id 1x in the output. no id shouldt appear twice or more. cause just the highest count is needed. thanks and sorry for the bad english.
Array
(
[0] => stdClass Object
(
[posts_id] => 336
[value] => 8
[how_many] => 2
)
[1] => stdClass Object
(
[posts_id] => 336
[value] => 7
[how_many] => 1
)
[2] => stdClass Object
(
[posts_id] => 380
[value] => 5
[how_many] => 1
)
[3] => stdClass Object
(
[posts_id] => 378
[value] => 7
[how_many] => 1
)
[4] => stdClass Object
(
[posts_id] => 329
[value] => 2
[how_many] => 1
)
[5] => stdClass Object
(
[posts_id] => 327
[value] => 3
[how_many] => 1
)
)
You can filter the resulting groups in a HAVING clause based on a match against a subquery for the maximal count:
SELECT posts_id, value, COUNT(*) AS how_many
FROM wp_mrp_rating_item_entry_value t1
GROUP BY posts_id, value
HAVING how_many = (
SELECT COUNT(*)
FROM wp_mrp_rating_item_entry_value t2
WHERE t2.posts_id = t1.posts_id
GROUP BY t2.value
ORDER BY COUNT(*) DESC
LIMIT 1
)

Insert Array values, multiple rows

I'm trying to record some information on a database. My post looks like this:
Array
(
[Action] => 1000
[Date_Stat] => 07/02/2013
[Date_Final] => 07/02/2013
[Product_Id] => Array
(
[0] => 2
[1] => 6
[2] => 1
)
[Conversion] => Array
(
[0] => 1,20
[1] => 1,00
[2] => 2,03
)
[ValueMin] => Array
(
[0] => 2,00
[1] => 1,58
[2] => 2,70
)
[ValueMax] => Array
(
[0] => 2,50
[1] => 1,98
[2] => 2,90
)
[ValueMedio] => Array
(
[0] => 2,20
[1] => 1,68
[2] => 2,80
)
)
HOW can I insert all this on database the right way?
I'm not sure about the best way to design the tables and store the information. I'm using this to make a PRICE TABLE with starting date, final date and list all products with prices.
Also I'm thinking what is the best method. There are 2 possibilities I think about
Date_Start | Date_End |Product_Id | ValueMin | ValueMax | ValueMedio | Conversion
02-02-2013 02-03-2013 1 1.00 2.00 3.00 4.00
02-02-2013 02-03-2013 2 1.00 2.00 3.00 4.20
02-02-2013 02-03-2013 3 1.00 2.00 2.00 4.40
OR (using implode and putting all values on the same row)
Date_Start | Date_End |Product_Id | ValueMin | ValueMax | ValueMedio | Conversion
02-02-2013 02-03-2013 1,2,3 1,1,1 2, 2,2 3,3,2 4, 4.3, 4.4
Thanks a lot!
Choose the option mentioned first. Selecting Rows will become much easier if you do it that way.
To insert the records, use a simple prepared Statement (PHP Manual) and use a for-Loop.
I'd suggest a little tweak over the first option. If you create a separate table (Something along the lines of "Prices") like this:
id|DateStart|DateEnd|
1|02-02-2013|02-02-2013|
And then, in the table you suggested, you'd replace the date range for the PriceId (Foreign Key to this table). That way it'll be easier for you to maintain the consistency over changes on date ranges.

Categories