Deleting records based on row count and conditions - php

I'm trying to create a quick-fix script in order to delete some records and get the data back on track.
Originally I had sales records inserting and using a quantity value to create an equal number of records. So I if I inserted a record with a quantity value of 12, then I would insert 12 of that record. This gave each SKU it's own record so that individual ones could have dates updated.
However, this has changed and I now need to do it based on store locations rather than quantity so I have too many records in some cases.
If I run the script with the current query (for dealer number 145) it selects all skus they have ordered this year, as expected. I need to now run a delete statement that takes a row count of each sku and compares it to the storefront value from the join.
So, if storefronts = 10 and there are 25 records for that sku/dealer combo, then I need to delete the oldest 15. The logic here is for each sku/dealer combo where curdate() < expire_date there should only be x number of rows equal to storefronts
I'm trying to test this with dealer 145, who has 10 stores. So for all records this year where curdate() is before the expiration, there should be no more than 10 records for each sku, if that makes sense.
$selectRecords = "
SELECT p.sku_id, p.dealer_id, p.start_date, p.expire_date, p.quantity, s.storefronts, s.dealer_id
FROM placements p
inner join storefronts s on p.dealer_id = s.dealer_id
WHERE p.dealer_id = 145
and start_date > '2018-01-01'
order by start_date asc;
";
try{
$currentRecords = $MysqlConn->prepare($selectRecords);
$currentResult = $currentRecords->execute();
$currentCount = $currentRecords->rowCount();
echo "Open Orders: " . $currentCount . "\n"; //returns correct count
}catch(PDOException $ex){
echo "QUERY FAILED!: " .$ex->getMessage();
}
$currentArray = [];
while($row = $selectRecords->fetch(PDO::FETCH_ASSOC)){
//pseudo code
foreach(sku_id){
if(rowCount > storefronts){
delete starting with oldest start_date
until row count == storefronts
}
}
}
I feel like it shouldn't be too complicated but I'm really stuck on how to execute this exactly.
Here's a fiddle with data examples:
http://sqlfiddle.com/#!9/c0dd6

Related

Mysql join returns results in multiple rows instead of one for every instance

I have three tables: tbl_days, tbl_slots and tbl_bookings as follows.
Customers are supposed to book for a slot in a day.
Am using the following query:
$slots = $this->common->slots();
if ($slots != NULL) {
foreach ($slots as $C):
$start = $C->start;
$stop = $C->stop;
$slotspace= $start." to ".$stop;
$available='Available';
$booked ='Booked';
$sum_col[] = " IF(tbl_bookings.slot_id =". $C->id.",'".$booked."','".$available."') AS '" . $slotspace . "'";
endforeach; }
$sqlquery = $this->db->query("SELECT tbl_days.date_day,
" . implode(",", $sum_col) . "
FROM tbl_days
LEFT JOIN tbl_bookings ON tbl_bookings.date = tbl_days.date_day
LEFT JOIN tbl_slots ON tbl_slots.id = tbl_bookings.slot_id
LEFT JOIN tbl_fields ON tbl_fields.id = tbl_bookings.field_id
");
return $sqlquery->result();
However, the results display as:
Intended result should be:
Please note how booking information displays on multiple rows for the same date.
Dates to be from the date today (for the next 7 days from today)
Display slots for the day on one row.
Display the date regardless of if there is a booking or not, like in date 29th.
Kindly help me on how to go about this.
Please note that am using datatables.
So each entry gets displayed in a new row instead of everything that's connected to each other in 1 row, right? I had the same problem in the past and the solution is a second foreach. The second one should look at all the records and see if one is connected to another.
See my question: Each value is displayed in a new row HTML table

Only showing lines with more that 20 participants

I have a problem i hope you can help me out with.
To break it down, i have a table in the database where i create events, it's called "dansetimer" and for that i have a table called for the participants on the events, called "transak"
I want to count how many events within a given time, had more than 20 participants.
I have made this for a start, and it's also very good, but i cant see how to count, how many events i end up with, of course i can just count the list manually, but i really want to get PHP to count it.
$hentgg = mysql_query("SELECT * FROM dansetimer WHERE dato BETWEEN $fra AND $til");
if(mysql_num_rows($hentgg)) {
while($visgg = mysql_fetch_array($hentgg)) {
$result=mysql_query("SELECT count(*) as total FROM transak WHERE produkt = '$visgg[id]'");
$data=mysql_fetch_assoc($result);
if($data['total'] > 20) {
echo $visgg[title];
}
}
} else {
echo "Ingen resultater";
}
With the above code i'm able to retrieve the events and get them listed.
With this code:
$result=mysql_query("SELECT count(*) as total FROM transak WHERE produkt = '$visgg[id]'");
$data=mysql_fetch_assoc($result);
I can count how many participants there are on the event, and with the if statement, testing if there are more than 20, i can hide the events, that dont have more participants.
But do you have a great idea for how i can write "Within the given time, you held 23 events with more than 20 participants" or something like that.
You could keep an extra counter in the loop, so you can see how many events have over 20 participants:
// At the start of your script
$large_events = 0;
...
// In your loop:
if($data['total'] > 20) {
echo $visgg[title];
$large_events++;
}
But I think it's easier, and probably faster too, to let SQL give you already some more details. In your solution it will query the participants for each event, so if someone has 1000 events, each with 20 participants or less, your database has to do 1001 queries, end the end result is 'Ingen resultater'.
So, change the query to this:
SELECT *
FROM
( SELECT
dt.*,
(SELECT count(*) FROM transak WHERE produkt = dt.id) AS total_participants
FROM dansetimer dt
WHERE dato BETWEEN $fra AND $til
)
WHERE
total_participants > 20
ORDER BY
dato,
title
This query returns only events with more than 20 participant, and it will return the number of participants per event. So you can just fetch this query result into a simple array and display each item to show the title, number of participants and other information. And the length of the array is the number of 'large' events.
PS: Did you know that the mysql_* functions are old and are removed in PHP 7? I think it's time for an upgrade to PDO.
Need to use this below query and you will get desired output (I want to count how many events within a given time, had more than 20 participants.).
SELECT count(*) FROM dansetimer dt WHERE (SELECT count(*) FROM transak WHERE produkt = dt.id)>=20 and dato BETWEEN $fra AND $til

php query, price change depending on hour of the day

i have the following table with values from a sql query:
now depending on the hour of the day, i want to be able to change the values.
for example, its late in the afternoon, i choose the option 3 dagen EUR 20.00. Since right now this day is already almost over, i should pay a smaller amount for 1 dag (example EUR 4), and then the price for 2 dagen EUR 14.00, so at this hour of the day the box 3 dagen should show EUR 18.00
So i know how to get the current hour, but how can i change my query to reflect this?
This is the query i used to get this table:
<?php
echo "<h2>".$lang['pagina3_dagen']."</h2>";
$number=="0";
echo "<table class='prijs'>";
echo "<tr>";
$query="SELECT * FROM $tabel WHERE fietstype='$fietskeuze'";
$result=mysql_query($query) or die ("Ophalen prijzen mislukt: ".mysql_error());
while ($row=mysql_fetch_array($result)) {
$days=$row[days];
$price=$row[price];
if ($days=="1") $writeday=$lang['pagina3_1dag'];
if ($days >="2") $writeday=$lang['pagina3_meerderedagen'];
echo "<td class='prijs'><h2><a href='framemaat.php?lang=".$_SESSION['lang']."&naam=".$naam."&postcodehuisnummer=".$postcodehuisnummer."&fietskeuze=".$fietskeuze."&opties=".$opties."&optieid=".$optieid."&days=".$days."'>".$days." ".$writeday."<br>EUR ".$price."</a><br>";
$number++;
if ($number=="5") {echo "<tr>"; $number="0";}
}
echo "</tr>";
echo "</table>";
?>
i was thinking in pseudo-like code something like this:
$currenthour = date("H", time());
if (($currenthour >="13") && ($currenthour <"15"))
{
$pricedag1=($pricedag1-3eurodiscount);
price in table result for 3 dagen=($pricedag1+$priceofdag2)
}
but how to get the price of the previous day? so the second to last value coming from the query?
I'm not entirely sure I understand the details of your table, but here's a shot:
Why not have a separate table that holds discounts for your products (dagens?) ? This way, you can query your products and join it against the discount table.
// you can decide the data type
CREATE TABLE Discounts (discount_id, product_id, start, end, discount);
then you could left join with your product table
SELECT p.*, d.discount
FROM products p
LEFT JOIN discounts d ON d.product_id = p.product_id
AND start <= ? AND end >= ?;
So after you've received your result set, you can check whether discount is empty or not. If it's not, apply the necessary discount.
if (!empty($row['discount']) {
$price = $price - $row['discount'];
}
Of course, you could take it a step further and determine types of discounts - percentage off, dollar off, etc.

To compile a product listing, specifically a price, how can I use two tables to build a total price overall for product?

I am trying to produce a shopping site where I am selling items that fluctuate in price daily (precious metals). I have a table (products) that will contain a multiplier (something like "1.1") for each product. I basically don't want to have to go into my tables and change the prices of hundreds of items every day. My idea is to create another table where I will simply change the price field with the daily value each day. How can I make the final product price total the multiplier from one table multiplied by the entered daily price from another table. Or, is there a better way than using two tables? Here's the coding so far using just one table with a defined price :
if (isset($_GET['id'])) {
//Connect To Mysql Database
include"storescripts/connect_to_mysql.php";
$id = preg_replace('#[^0-9]#i','',$_GET['id']);
//Use This VAR To Check To See If This ID Exists, If Yes Then Get Product
//Details, If No Then Exit Script and Give Message Why
$sql = mysql_query("SELECT * FROM products WHERE id='$id' LIMIT 1");
$productCount = mysql_num_rows($sql);
if ($productCount > 0) {
//Get All The Product Details
while ($row = mysql_fetch_array($sql)) {
$product_name = $row["product_name"];
$price = $row["price"];
$details = $row["details"];
$category = $row["category"];
$subcategory = $row["subcategory"];
$date_added = strftime("%b %d, %Y",strtotime($row["date_added"]));
}
} else {
echo "That Item Does Not Exist";
exit();
}
} else {
echo "Data To Render This Page Is Missing";
exit();
}
mysql_close();
So, how about a response that isn't the usual mysql_* related pedantry?
In the following schema I've broken the materials table away from the listed price so that they can be stored according to date. You might find this useful for records and/or invoicing.
TABLE products
prod_id INT PK
prod_name VARCHAR
prod_price DECIMAL
mat_id INT FK
...
TABLE materials
mat_id INT PK
mat_name VARCHAR
...
TABLE material_pricing
mat_id INT FK PK
mat_price_date DATE PK
mat_price_factor DECIMAL
SELECT
p.prod_name,
p.prod_price * pr.mat_price_factor AS 'cur_price'
FROM products p INNER JOIN materials m
ON p.mat_id = m.mat_id
INNER JOIN material_pricing pr
ON m.mat_id = pr.mat_id
WHERE mat_price_date = TODAY()
I'm trying to think of a way to change the query to grab the last defined material_pricing entry for the relevant material, but I'm having a tough time lining up the data for a subquery...
edit: this should do the trick
SELECT
p.prod_name,
p.prod_price * pr.mat_price_factor AS 'cur_price'
FROM products p INNER JOIN materials m
ON p.mat_id = m.mat_id
INNER JOIN (
SELECT p1.*
FROM material_pricing p1 INNER JOIN (
SELECT mat_id, MAX(mat_price_date) 'mat_price_date'
FROM material_pricing
WHERE mat_price_date <= $target_date
GROUP BY mat_id
) p2
ON p1.mat_id = p2.mat_id
AND p1.mat_price_date = p2.mat_price_date
) pr
ON p.mat_id = pr.mat_id
Where $target_date in the innermost subquery would be replaced by either today's date, the TODAY() mySQL function, or the date of the invoice being displayed.

Group by mysql data that i need to expand one cell

I'm working on a job at the minute where all the products within the store need to be brought in and show how many orders have been put through in-between that time period which was easy to do, but it also in the same table needs to split the quantity of the orders of that product into the separate months that it was ordered in, is there any way to expand the data from one cell that's been group and do a count on it and then separate it into sub months?
$this->obDb->query ="SELECT vSku,fOrdertime,iOrderStatus,fPrice,SUM(iQty) as iQty,tShortDescription,fBuyprice as totalBuyPrice, vTitle FROM ".ORDERS.",".ORDERPRODUCTS." WHERE iOrderid_FK=iOrderid_PK AND ";
$this->obDb->query.=$statusquery;
if(isset($this->request['start_date']) & $this->request['start_date']>0){
$this->obDb->query.=" AND tmOrderDate >='".$this->request['start_date']."'";
}else{
$this->err=1;
$this->errMsg=INVALID_START_DATE."<br>";
}
if(isset($this->request['end_date']) & $this->request['end_date']>0){
$this->obDb->query.=" AND tmOrderDate <='".$this->request['end_date']."' GROUP BY vTitle";
}else{
$this->err=1;
$this->errMsg.=INVALID_END_DATE;
}
if($this->err==0){
$queryRs = $this->obDb->fetchQuery();
$recordCount=$this->obDb->record_count;
if($recordCount>0){
$this->ObTpl->set_var("TPL_VAR_FROMDATE", $this->libFunc->dateFormat2($this->request['start_date']));
$this->ObTpl->set_var("TPL_VAR_TODATE", $this->libFunc->dateFormat2($this->request['end_date']));
for($i=0;$i<$recordCount;$i++)
{
$this->ObTpl->set_var("TPL_VAR_STATUS","Incomplete");
if($queryRs[$i]->iOrderStatus==1){
$this->ObTpl->set_var("TPL_VAR_STATUS","Complete");
}
If I understand what you're asking you could try
SELECT datecol, COUNT(id)
FROM your_table
WHERE datecol BETWEEN date1 AND date2
GROUP BY productId, YEAR(datecol), MONTH(datecol)
ORDER BY datecol

Categories