multidimensional array query mysql - php

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.

Related

Combining data from multiple arrays into a final array for output in CSV

I'm trying to restructure my arrays so that I can get the desired output in one final array that will be used to fill a csv, eventually spreadsheet.
My first msyql query and the resulting array give me this structure:
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-
)
)
So I get 3 records, each for the same product (sku_id) but a different customer(dealer_id). Then I match this data up in a similar table in DB2 to get quantity for each order of the sku_id. That 2nd query/array shows this:
Array
(
[0] => Array
(
[CSTNOC] => 1976
[TOTALQTY] => 2
)
[1] => Array
(
[CSTNOC] => 5400
[TOTALQTY] => 5
)
[2] => Array
(
[CSTNOC] => 11316
[TOTALQTY] => 14
)
)
However, this is what 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.
I have everything I need to get there, but how can I structure a final array to get my desired outputs like above?
FULL SCRIPT:
$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[] = $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);
foreach($skuResult as $skuRow){
while($dealerRow = odbc_fetch_array($dealerRslt)){
$dealerResult[] = $dealerRow;
}
}
print_r($dealerResult);
}

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.

make a multidimensional array php mysql

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.

PHP and MySQL to perform a join on a MAX column

I've read a few of the similar threads on here and after many hours of banging my head, I still can't get this to work.
I have 2 tables within MySQL:
- bookings
- booking_status_history
The structure and data of the booking table:
id pt_id client_id timestamp notes
62 30 15 2015-02-02 07:00:00
The structure and data of the booking_status_history table:
(note booking_id is a foreign key to the booking table above)
id booking_id timestamp description details status
11 62 2015-02-02 00:40:42 Client made Booking (pending) test_detailsi pending
12 62 2015-02-02 00:40:45 PT confirmed booking (confirmed) test_details2 pending
18 62 2015-02-02 02:45:15 Client cancelled Booking (Medical Emergency) test_details3 pending
What I am trying to achieve is getting the LATEST value from the status column for each booking (this test data only shows 1 booking and 3 history values).
At the moment I have only achieved pulling back all of the history results and not just the latest row.
I am using the following PHP MySQLi library: https://github.com/joshcam/PHP-MySQLi-Database-Class#join-method
This is my current code which seems to return all of the history. I've tried using variations of MAX and GROUPBY as I've seen work for others in older threads but for some reason I just can't apply it to this scenario.
$date = date('Y-m-d H:i:s', time());
$this->db->join("booking_status_history h", "b.id=h.booking_id", "LEFT");
$this->db->where('client_id', $id_param);
$this->db->where('b.timestamp', $date, ">");
$this->db->where('h.status', 'pending');
$this->db->orderBy("b.timestamp","desc");
$next_booking = $this->db->get("booking b", NULL, "b.*, h.status");
return $next_booking;
As you can see from the output below, this is returning all 3 history values:
Array (
[0] => Array (
[id] => 62
[pt_id] => 30
[client_id] => 15
[timestamp] => 2015-02-02 07:00:00
[notes] => [status] => pending
)
[1] => Array (
[id] => 62
[pt_id] => 30
[client_id] => 15
[timestamp] => 2015-02-02 07:00:00
[notes] => [status] => pending
)
[2] => Array (
[id] => 62
[pt_id] => 30
[client_id] => 15
[timestamp] => 2015-02-02 07:00:00
[notes] => [status] => pending
)
)
I appreciate not everyone is going to be familiar with this PHP library so even if someone can explain it to me via raw SQL, that would be awesome.
What I am trying to do is (in pseudo code):
SELECT everything
FROM bothtables
WHERE booking.id=booking_status_history.booking_id
AND latest entry in booking_status_table
I hope that makes sense. It's 5am and I've been up all night having a huge code block.
Thanks!
This is what seems to have cracked it for me! Many thanks to Jhecht for spending time helping me out :-)
SELECT b.*, h.booking_id, h.details, h.status FROM booking b JOIN booking_status_history h ON b.id = h.booking_id WHERE h.id = (SELECT MAX(id) FROM booking_status_history WHERE booking_id = b.id)
You can go for comparison with id from status table.It will go like this.
SELECT * FROM booking_status_history_table bs,booking_table bt
WHERE bs.booking_id=bt.id
and bs.id in
(select max(id) from booking_status_history_table group by booking_id)
The stock solution looks like this...
SELECT b.*
, x.timestamp
, x.description
, x.status
FROM booking b
JOIN booking_status_history x
ON x.booking_id = b.id
JOIN
( SELECT booking_id,MAX(id) max_id FROM booking_status_history GROUP BY booking_id ) y
ON y.booking_id = x.booking_id
AND y.max_id = x.id;

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