I have "price offer" items under certain processes;
PROCESS 1
index no 0 price offer a count=1 ($selected_price_offers_cnt)
PROCESS 2
index no 1 price offer b count=3 (3+1=4)
index no 2 price offer c count=3 (3+1=4)
index no 3 price offer d count=3 (3+1=4) 3=selected_price_offers_cnt, 1=$previous, 4=$next
PROCESS 3
index no 4 price offer e count=2 (2+4=6)
index no 5 price offer f count=2 (2+4=6) 2=selected_price_offers_cnt, 4=$previous, 6=$next
What I need to do is to print "scale sub total" only below the LAST price offer item of EACH PROCESSES. In other words, below a, d and f.
In order to do that I try to compare the latest count of the price offers from the beginning (1, 4 and 6) with the current row index no + 1.
If we arrive at the last price offer of a PROCESS X, its count will be == index no + 1 (like at process offer d count 4 = index no 3 + 1).
So I need to keep $previous variable updated with $next for the following PROCESS Y.
My code takes unnaturally long time to finish execution and at last it prints only one sale sub total line.
(As this code is used inside Drupal views global php field, SQL queries are arranged to work there and they return correct values, no problem there.)
Any approaches other than while...loop is also welcomed.
<?php
$process_nid = $row->nid_3;
$current_index_no = $view->row_index; //the number of the row that is being processed
$selected_price_offers = db_query("SELECT entity_id FROM drupal_field_data_field_process WHERE bundle = 'price_offer' AND deleted = '0' AND field_process_nid = {$process_nid} AND entity_id IN (SELECT content_id FROM drupal_flag_counts WHERE fid='18' AND content_type='node' AND COUNT = '1')");
$selected_price_offers_cnt = db_query("SELECT COUNT(entity_id) FROM drupal_field_data_field_process WHERE bundle = 'price_offer' AND deleted = '0' AND field_process_nid = {$process_nid} AND entity_id IN (SELECT content_id FROM drupal_flag_counts WHERE fid='18' AND content_type='node' AND COUNT = '1')")->fetchField();
$previous = 0;
while($current_index_no) {
$next = $selected_price_offers_cnt + $previous; // add the previous to the current amount
if ($next == ($current_index_no+1)) {
$previous = $next; // save the new price offer count to the $previous in order to use it at the next row
// this part below works as expected
$sum1 = 0;
foreach($selected_price_offers as $item) {
$po_item= $item->entity_id;
$scale1 = db_query("SELECT field_sub_total_scale_1_value FROM drupal_field_data_field_sub_total_scale_1 WHERE bundle = 'price_offer' AND deleted = '0' AND entity_id = {$po_item}")->fetchField();
$sum1+= $scale1;
}
print "scale sub total: ".number_format($sum1,2,",","."). " TL";
}
else {
echo "";
}
}
?>
Related
Im pulling data from 2 different WordPress tables and looping through to get the appropreate data into a table row.
$tid = $_POST['pqrnum']; //get estimate number
$results = $wpdb->get_results('SELECT * FROM eqnum WHERE id='.$tid); //getting estimate data
$pArray = explode(',', $results[0]->pnum); //creating array of product numbers in estimate
$ptable = "<table>"; //create table
$presults = $wpdb->get_results('SELECT * FROM eparts'); //getting product data
$pres= count($presults); //products array count
for($l = 0; $l <=count($pArray); $l++){ //loop through each product in the array
$item = $pArray[$l]; //getting item number start 0
$titem = $item + 1; //adding 1 to $item without disturbing it because product array starts at 1
for ($x = 1; $x <= $pres; $x++) { //looping through product array
if($titem == $presults[$x-1]->id){ // if estimate item = product number
$ptable .= "<tr><td>item num ". $titem ." presults id ".$presults[$x-1]->id." presults name ".$presults[$x-1]->name."</td></tr>";
}
}
}
$ptable .= "</table>";
not sure why, but it seems to be printing an extra row, in this particular example there should be 3 rows, however this is the response:
item num 1 presults id 1 presults name Back up Alarm
item num 10 presults id 10 presults name Oil Filter
item num 11 presults id 11 presults name Spark Plug
item num 1 presults id 1 presults name Back up Alarm
as you can see the first and last lines are the same, it should be just the top 3, not 4.
just trying to determine why the extra row, any help appreciated.
Alex had the answer using < rather than <=, I thought I had tried that before but prefect thank you.
I am trying to make a function where the following should happen:
Retrieve the ID value of all users in database.
Retrieve all numbers belonging to each user from an other table in the same database.
Add all the numbers belonging to each user together.
By using my code (see below), step 1 and 3 is working. At step 2, it is looping the correct amount of times but in every loop it retrieves the numbers belonging to the first ID from step 1.
Example:
Step 1 finds the following IDs: 1, 2, 3 and 4.
Step 2 loops 4 times, but retrieves the numbers belonging to ID 1 every time instead of retrieving the numbers to ID 1 in the first loop, ID 2 in the second etc.
My PHP:
$users_get = mysqli_query($conn,"SELECT id FROM users");
$users_num = mysqli_num_rows($users_get);
$users_list = array();
while($users_row = mysqli_fetch_array($users_get)){
$users_list[] = $users_row;
}
foreach($users_list as $users_row){
$users_items[] = array(
'id' => $users_row['id']
);
}
for($loop1 = 0; $loop1 < $users_num; $loop1++){
$numbers_get = mysqli_query($conn,"SELECT number FROM users_numbers WHERE userid = '".$users_items[$loop1]['id']."'");
$numbers_num = mysqli_num_rows($numbers_get);
$numbers_list = array();
while($numbers_row = mysqli_fetch_array($numbers_get)){
$numbers_list[] = $numbers_row;
}
foreach($numbers_list as $numbers_row){
$numbers_items[] = array(
'number' => $numbers_row['number']
);
}
$numbers_added = 0;
for($loop2 = 0; $loop2 < $numbers_num; $loop2++){
$numbers_added = $numbers_added + $numbers_items[$loop2]['number'];
}
}
I later added som echos to display the IDs and numbers that is retrieved and got the following result:
User ID: 1
Amount of numbers: 4
Numbers:
4 (Belonging to ID 1)
7 (Belonging to ID 1)
5 (Belonging to ID 1)
2 (Belonging to ID 1)
Total: 18
User ID: 2
Amount of numbers: 0
User ID: 3
Amount of numbers: 3
Numbers:
4 (Belonging to ID 1)
7 (Belonging to ID 1)
5 (Belonging to ID 1)
Total: 16
The amount of numbers for ID 3 is correct, however the 3 retrieved numbers belongs to ID 1.
Another observation I made was if I edit the SELECT query inside loop 1:
"SELECT number FROM users_numbers WHERE userid = '".$users_items[$loop1]['id']."'"
And manually selects an ID, example:
"SELECT number FROM users_numbers WHERE userid = '3'"
Then it retrieves the correct numbers belonging to ID 3.
After hours of trying to figure out what I'm doing wrong I still haven't found anything, so any help is really appreciated! Is there something I can do with my current code to fix it, or maybe there is some other ways to achieve the desired function?
Based on the comments on my question, I ended up with the following code:
$users_get = mysqli_query($conn,"SELECT a.id, SUM(b.number) AS number FROM users AS a INNER JOIN users_numbers AS b ON a.id = b.userid GROUP BY a.id ASC");
$loop1 = 0;
while($users_items[] = mysqli_fetch_array($users_get){
echo "ID: ".$users_items[$loop1]['id']." - Num total: ".$users_items[$loop1]['number']."<br />";
$loop1++;
}
The echo inside the while is only for testing purposes. When I run this, it displays a nice list with all the user IDs and the sum of each users numbers.
I have a Part Management system I've created in PHP with MySQL. What I'm trying to create is something that will generate the next Part Number for me. All part numbers start with a 3 letter prefix (which is determined by the product family/category) followed by their number.
For example 'ABC001'
What I have below is something that I'd like to use to determine what the next number is having already 'ABC001', 'ABC002' & 'ABC003' so I would like it to recognize what the next number is by querying until the query comes back false because that product number doesn't exist yet.
$abc_query = "SELECT * FROM products WHERE id LIKE 'ABC%'";
$abc_result = $mysqli2->query($abc_query);
while($row = $abc_result->fetch_assoc()) {
$rowid = $row["id"];
$pnumber = substr($rowid, 3, 3);
echo $pnumber. '<br/>';
$int = (int)$pnumber;
$abc_query2 = "SELECT * FROM products WHERE id 'ABC" . sprintf('%03s', $int);
for ($abc_query2 = true; $abc_query2 = false; $int++){
echo $int;
}$abc_nextnumber = $int +1;
}
$abc_newnumber = 'ABC' . sprintf('%03s', $abc_nextnumber);
echo $abc_newnumber;
The result I get is
001
002
003
005
ABC006
However the result should be..
001
002
003
ABC004
code update I've updated the code but it doesn't seem to stop at ABC004 if I have an 005. It will go to 006.
You should have the db do this instead of your app:
select t.id_prfx, max(t.id_num) as latest_num from
(select substring(id, 1, 3) as id_prfx,
cast(substring(id,4) as integer) as id_num) t
group by id_prfx
This will give you a result table where you get the highest part number for each prefix.
If you really really only want prefixes of 'ABC' then:
select max(cast(substring(id,4) as integer)) as max_num from table
where id LIKE 'ABC%'
Could you try this query?
SELECT MAX(SUBSTR(id, 4)) as last_id FROM products WHERE SUBSTR(id, 1, 3)='ABC'
EDİT:
products TABLE
==============
ABC001
ABC002
ABC003
ABC005
==============
We want to find 4 in products table.
SELECT SUBSTR(t1.id, 4) + 1 as POSSIBLE_MIN_ID
FROM products t1
WHERE NOT EXISTS (
SELECT *
FROM products t2
WHERE SUBSTR(id, 1, 3)='ABC' AND SUBSTR(t2.id, 4) = SUBSTR(t1.id, 4) + 1
) LIMIT 1
RESULT:
POSSIBLE_MIN_ID : 4
If anyone knows how I can have it add automatic zeros to the into the query (as it will be different amount of 0s once it gets to 'ABC011') instead of typing them in that would also be very helpful.
Here's how to automatically handle the prepended zeroes.
$sql3 = "SELECT * FROM products WHERE id 'ABC" . sprintf('%03s', $int);
I have a table called expenses. There are numerous columns but the ones involved in my php page are date, spplierinv, amount. I have created a page that lists all the expenses in a given month and totals it at the end. However, each row has a value, but many rows might be on the same supplier invoice.This means adding each row with the same supplierinv to get a total as per my bank statement. Is there anyway I can get a total for the rows based on the supplierinv. I mean say I have 10 rows. 5 on supplierinv 4, two on supplierinv 5 and 3 on supplierinv 12, how can a get 3 figures (inv 4, 5 and 12) and the grand total at the bottom. Many thanks
Do you need to show the individual expense rows as well as all the totals? If not, you can group by the supplierinv column and sum the amounts:
select supplierinv, sum(amount) as invoice_amount
from expenses group by supplierinv
then you can simply add all the invoice_amount values client-side to get the grand total.
if you do need each expense row, you can do the invoice aggregation client-side fairly easily:
$invtotals = array();
$grand_total = 0;
foreach (getexpenses() as $row) {
$supplierinv = $row['supplierinv'];
if (!array_key_exists($supplierinv, $invtotals)) {
$invtotals[$supplierinv] = 0;
}
$invtotals[$supplierinv] += $row['amount'];
$grand_total += $row['amount'];
}
another approach, if you want to show the table split up into invoices, is to just ensure the results are ordered by supplierinv and then:
$grand_total = 0;
$invoice_total = 0;
$current_invoice = -1;
foreach (getexpenses() as $row) {
if ($current_invoice > 0 && $current_invoice != $row['supplierinv']) {
show_invoice_total($current_invoice, $invoice_total);
$grand_total += $invoice_amount;
$current_invoice = $row['supplierinv'];
$invoice_total = 0;
}
$invoice_total += $row['amount'];
show_expense($row);
}
if ($current_invoice > 0) {
show_invoice_total($current_invoice, $invoice_total);
$grand_total += $invoice_amount;
}
show_grand_total($grand_total);
You can have the database do the aggregation for each invoice and the grand total like so:
select date, supplierinv, amount,
sum(amount) over(partition by supplierinv) as invoice_amount,
sum(amount) over()
from expenses
although you still have to do some post-processing to display this sensibly, so this doesn't really gain anything imho.
I have to calculate a price based on a rate structure along these lines:
$303.00 fixed price up to 500 units
$0.023 additional per unit from 501-10,000 units
$0.022 additional per unit from 10,001-25,000 units
$0.021 additional per unit from 25,001-50,000 units
I'm a little lost on setting up a database structure and algorithm (the larger sticking point) for calculating this. Has anyone done this? Is there a nice, elegant way of calculating this sort of thing?
edit: As an example, a 25,100 unit run would cost $303.00 for the first 500 units, $218.50 for the next 9,500 units, $330.00 for the next 15,000 units, and $2.10 for the next 100 units, for a total of $853.60.
It wouldn't be a simple 25,100 * $0.021 calculation - I'm well aware of how to select and calculate that.
Similar to the way income tax is assessed - on a marginal basis.
I assume you want something flexible, otherwise it would be trivial to hardcode it.
You could use a pricing table:
ID MAX FIX UNIT
1 500 303 0
2 9500 0 .23
3 15000 0 .22
4 25000 0 .21
Then you could calculate as follows:
$items = ?;
$cost = 0;
$rows = get_rows("select max, fix, unit from pricing order by id asc");
foreach ($rows as $r)
{
if ($items <= 0)
break;
$cost += $r['fix'] + min($r['max'], $items) * $r['unit'];
$items -= $r['max'];
}
I have assumed that you want the algorithm in PHP.
Python
from collections import namedtuple
RateRule= namedtuple( 'RateRule', ['qty_band','fixed','per_unit'] )
rate_table = [
RateRule(500, 303, None),
RateRule(9500, None, 0.023),
RateRule(15000, None, 0.022),
RateRule(25000, None, 0.021)
]
def total_price( units, rate_table ):
# Base
total = rate_table[0].fixed
units_purchased_so_far = rate_table[0].qty_band
# Whole Price Bands
rule = 1
while units > units_purchased_so_far + rate_table[rule].qty_band:
total += rate_table[rule].qty_band * rate_table[rule].per_unit
units_purchased_so_far += rate_table[rule].qty_band
rule += 1
# Units within the top Price Band
if units > units_purchased_so_far:
total += (units - units_purchased_so_far) * rate_table[rule].per_unit
return total
Something like this:
Product
-------
[PK] ProductID
Price
-----
[PK] PriceID
[FK] ProductID
Price
QtyMin
QtyMax
So effectively a 1-many relationship between product and price. You could use a sentinel value for the maximum if you require a flat rate regardless of quantity.
SELECT
CASE is_fixed_price
WHEN 1
THEN unit_price / ?
ELSE
unit_price
END
FROM rate_structure
WHERE ? BETWEEN min_qty AND max_qty
Where ? is the quantity your customer wants to order. Syntax off the top of my head, for mysql 5.x. The side effect of this is potential rounding error accumulation.
What I wound up doing:
size units fixed per
1 500 303.000 0.000
1 10000 0.000 0.023
1 25000 0.000 0.022
1 50000 0.000 0.021
function calculate_price($size, $quantity) {
global $db;
$price = 0;
$count = 0;
// fetch rates from the database
// note: $size is already sanitised by the calling function
$query = "SELECT units, flat, per FROM rates WHERE size={$size} ORDER BY units ASC";
$result = $db->query($query);
// step through the rates
while($rate = $result->fetch_object()) {
// figure out how many of our units fall within this tier
$tier_count = max(0, min($quantity - $count, $rate->units - $count));
// calculate the price for this tier, including any flat rate
$tier_price = $rate->flat + ($rate->per * $tier_count);
// add tier price and count to the totals
$price += $tier_price;
$count += $tier_count;
// store the last, largest number of units rate for any leftovers outside our tiers
$last_rate = $rate;
}
// if some of our units fall outside our defined tiers, use the last tier's values for them
if($count < $quantity) {
$tier_count = $quantity - $count;
$tier_price = $last_rate->flat + ($last_rate->per * $tier_count);
$price += $tier_price;
$count += $tier_count;
}
return $price;
}