I have two tables in one database that are emptied and replaced very frequently. Each table has well over 65,000 rows. I want to select two fields from the first table (LnsPriceUpdates), then take those values and compare and insert them into the second table (LnsCatalog) and want to do this for all 65,000 items in the database.
(Note: I want to do all this from a localhost)
Here's the current code I'm using:
public function testbananaAction()
{
$em = $this->getDoctrine()->getManager();
$query = $em
->createQuery(
'SELECT l.partnumber, l.level1Net FROM AppBundle:LnsPriceUpdates l WHERE l.level1Net IS NOT NULL'
)
->getResult();
foreach ($query as $row){
$partNo = $row['partnumber'];
$part = $em->getRepository('AppBundle:Lnscatalog')
->findOneBy(['partnoid' => $partNo]);
$dealerCost = $row['level1Net'];
if(isset($dealerCost) && isset($part)){
$partCheck = $part->getDealerCost();
if(!isset($partCheck)){
$part->setDealerCost($dealerCost);
$em->flush();
}
} else {
continue;
}
}
return new Response('yay');
}
Any ideas to accomplish this task without crashing would be helpful.
Can you achieve with a single Sql Update something like:
update Lnscatalog c
set c.dealerCost = (SELECT l.level1Net FROM AppBundle:LnsPriceUpdates l WHERE l.level1Net IS NOT NULL and l.partnumber=c.partnoid)
where c.dealerCost is null
and exists (SELECT l.level1Net FROM AppBundle:LnsPriceUpdates l WHERE l.level1Net IS NOT NULL and l.partnumber=c.partnoid)
You can speed up this query adding some index on the above table, as example:
ALTER TABLE LnsPriceUpdates
ADD INDEX LnsPriceUpdates_IDX_1 (level1Net, partnumber) ;
ALTER TABLE LnsPriceUpdates
ADD INDEX LnsPriceUpdates_IDX_2 (partnumber) ;
ALTER TABLE Lnscatalog
ADD INDEX Lnscatalog_IDX_2 (dealerCost) ;
Some reference about optimizing sql query can be found here, here and here
Hope this help
Related
I have two tables, tableA and tableB. They are connected by a foreign key on their IDs (ATableID, BTableID).
TableB has a stored procedure that allows rows to be archived, It has 2 columns in it named Available_Days and Available_Night. In TableA
There is also columns Available_Days and Available_Night, which are joined to tableB by a left join. If there is data in those columns in TableA, you must not be able to archive the row in TableB.
This is the stored procedure currently, I need help implementing the criteria explained above.
#BTableID VARCHAR(500) = '',
#UserArchived INT = 0
AS
DECLARE #Local BTableID VARCHAR(500)
DECLARE #LocalUserArchived INT
DECLARE #LocalSql NVARCHAR(500)
set #Local BTableID = #BTableID;
set #LocalUserArchived = #UserArchived;
set #LocalSql = 'UPDATE tableB
SET DateArchived = GETDATE(),
UserArchived = '+CAST(#UserArchived as NVARCHAR)+'
WHERE BTableID IN ('+# BTableID +')'
I am also open for any suggestions if the current direction isn't wise.
For full context, this stored procedure will be used in php Laravel framework where a user will be able to delete a row(TableB), unless that rows information is referenced elsewhere(TableA), in which case, they will be prompted to update the other table before attempting to delete again.
Once again, the desired result is to prevent archiving/soft deleting (preventing setting DateArchived = GETDATE()) a row if its information is referenced in another table.
UPDATE:
I've made two possible adjustments (currently unable to test them as I'm not able to access the db at the moment.)
set #LocalSql = 'UPDATE BTable
SET DateArchived = GETDATE(),
UserArchived = '+CAST(#UserArchived as NVARCHAR)+'
WHERE BTableID IN ('+#BTableID+')
WHERE NOT EXISTS (
SELECT FROM ATable at
WHERE tp.ATable_FK = tp.BTableID)'
and
set #LocalSql = 'UPDATE tableB
SET DateArchived = GETDATE(),
UserArchived = '+CAST(#UserArchived as NVARCHAR)+'
WHERE tableBID IN ('+#tableBID+')
LEFT JOIN tableA cm ON cm.tableAID = tp.tableBID
WHERE cm.tableAID IS NULL’
I'm not able to test them at this time but will update this post to let you know if either did the job. If you have any suggestions on improvements please leave a comment or answer. :)
SOLUTION:
I figured out a very simple solution to solve my issue. I forgot all about the archive/soft delete stored procedures and created two stored procedures for table A and table B which selects one record from the table. ie :
#TableAIB int
AS
SELECT
TableBID,
TableBDescription,
FROM TableB
WHERE TableBID = #TableBID
RETURN ##ERRO
and
GO
#TableAID int
AS
SELECT
TableAID,
TabelADescritption
FROM TableA
WHERE TableAID = #TableAID
RETURN ##ERROR
GO
these two two tables are connected via a foreign key(on tableAID and tableBID).
in the controller I then did this:
public function archive(int $id)
{
$tableA = tableA::find($id);
$tableB = tableB::find($id);
if ($tableA->TableAID == $tableB->TableBID){
return redirect()->route(‘myPage.index')
->with('warning', ’This can not be archived, it is being used in another row. ');
}
}
This is essentially saying that if the two stored procedure's ID's match, redirect to the index page with a warning.
I have table with favorites programm. I will add with ajax query to database favorite programm id's to table with user id. How I can skip a duplicate programm id with current user id.
I now create this method for skip duplicate values but not working in calling:
public function test($programm_id){
$fav = new \App\Favorite;
$user_id = Auth::id();
$fav_count = $fav::where('id_user', Auth::user()->id)->count();
$getFavorites = $fav::where('id_user', $user_id)->get()->toArray();
$userProgramms = $fav->where('id_user', $user_id)->select('id_program')->get()->toArray();
$bool = true;
foreach ($userProgramms as $array) {
foreach ($array as $value) {
if($value === $programm_id) $bool = false;
}
}
if($fav_count <= 5){
if ($bool){
$fav->id_user = Auth::user()->id;
$fav->id_program = $programm_id;
$fav->save();
}
}
}
Here my table:
Please see my method favorite() in this controller: Controller
My updated code can't more 1 saves to database.
$fav = new \App\Favorite;
$fav_count = $fav::where('id_user', Auth::user()->id)->count();
if($fav_count <= 5)
{
$fav->updateOrInsert(['id_user' => Auth::id()], ['id_program' => $post['id_program']]);
}
Every user can add to table max 6 favorite id programms
Add an unique index on the table:
ALTER TABLE `tableName` ADD UNIQUE `unique_index`(`id_user`, `id_program`);
and use the INSERT INTO ... OR UPDATE:
INSERT INTO t1 (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE c=c+1;
UPDATE t1 SET c=c+1 WHERE a=1;
In that manner your query will insert a new record if there isn't already a record with the same couple of id_user and id_program values, in case of it it'll perform an update on that row.
If you want to do it in PHP and assuming your values are stored in an array, you can use array_unique().
Check it out here: http://php.net/manual/en/function.array-unique.php
I want to create columns in a MySQL table and insert data into them. I already have some data inside of the table, I would like to add more. I am not sure how I would go about adding the other data. If someone could help me out, I would greatly appreciate it. Thanks.
My Source code looks like this:
if($is_array($asinXML){
foreach($asinXML as $asinXml){
$asinXmlLoaded = simplexml_load_file($asinXml);
foreach($asinXml->GetLowestOfferListingsForASINResult as $asinItem){
if(isset($asinItem['ASIN'])){
$asinValue = $asinItem['ASIN'];
} else {
$asinValue = '';
}
$asinErrorFound = 'Success' != $asinItem->attributes()->status;
if($asinErrorFound = TRUE){
$asinErrorFoundVal = 'Yes';
} else {
$asinErrorFoundVal = '';
}
if($asinErrorFoundVal == ''){
if(isset($asinItem->Product->LowestOfferListing->NumberOfOfferListingsConsidered){
$numberOfSellers = $asinItem->Product->LowestOfferListings->LowestOfferListing->NumberOfOfferListingsConsidered;
} else {
$numberOfSellers = '';
}
My Sql table looks something like this so far :
UPC ASIN SalesRank
Value Value1 Value2
I need to be able to insert a insert another column, then populate the column with information that corresponds to the ASIN Value. If that doesn't make sense, comment and i will elaborate. Thanks.
You can add a column (or columns) using ALTER TABLE statement. e.g.
ALTER TABLE mytable ADD my_new_col INT COMMENT 'my new column' ;
If you want to initialize that column on all of the rows that are already in the table, you can populate it with the value from another column on the row with an UPDATE statement:
UPDATE mytable SET my_new_col = some_old_col ;
If you just want to add a new row to the table, you can use the INSERT statement:
INSERT INTO mytable (my_new_col) VALUES (42);
you can ADD a calculated Column with the desired value.
If ASIN is numeric and you want to add taxes
ALTER TABLE myTable ADD MyNewColumn AS (ASIN * 1.08)
I have a transaction where I am inserting a new record into TableB and depending if there is not the proper supporting record in TableA I will also be inserting into TableA and using that Primary Key as a Foreign key entry into TableB.
$transaction=$connection->beginTransaction();
try
{
$tableA->IsActive = 'Y';
$tableA->save();
$model->TableAId = $tableA->TableAId; //not sure what to put here for $tableA->TableAId
$model->save();
$transaction->commit();
}
In this situation can I use Yii::app()->db->getLastInsertId(); for $tableA->TableAId;
Obviously accuracy is highly important here so I need to guarantee that the proper records align between TableA and TableB
Basically, Your comment looks perfect. $model->TableAId = $tableA->TableAId; // This is perfect!!
But code not. Following should be your code.
$transaction=$connection->beginTransaction();
try
{
$tableA = TableA::model()->findByPk("id"); OR $tableA = new TableA;
$tableA->IsActive = 'Y';
$tableA->save();
$model = new TableB;
$model->TableAId = $tableA->TableAId; //not sure what to put here for $tableA->TableAId // This is perfect!!
$model->save();
$transaction->commit();
}
Currently trying to find a way to do the following inside some form of loop (preferably without a performance hit on database).
I have 3 tables user_hours, user_calendar and hours_statistics. I need to first do:
SELECT user_calendar.date_start,
user_calendar.opportunity_id,
user_hours.user_id,
user_hours.agreed_hours,
user_hours.completed_hours,
user_hours.hours_committed
FROM user_calendar
JOIN user_hours
ON user_calendar.user_calendar_id = user_hours.user_calendar_id
WHERE user_calendar.date_start = CURRENT_DATE()
AND user_hours.completed_hours IS NULL
AND user_hours.hours_committed = 'accepted'
This query could return like the following:
http://i.imgur.com/5cJ5v.png
So for each opportunity_id and user_id returned i'd like to then do:
UPDATE user_hours
SET completed_hours = agreed_hours,
hours_committed = 'completed'
WHERE opportunity_id = {opportunity_id}
AND user_id = {user_id}
AND hours_committed = 'accepted'
AND completed_hours IS NULL
Note that {opportunity_id} and {user_id} would need to be looped at this point (see screenshot) because we need to go through each user on each opportunity.
Then for each updated record i'd need to then get the total hours like:
// Get hours they have done to send to statistics data table
SELECT sum(completed_hours) FROM user_hours WHERE user_id = {user_id} AND opportunity_id = {opportunity_id}
// Get the completed hours total somehow as a variable
$completed_hours = (from result above)
// Commit stats
UPDATE hours_statistics SET completed_hours = (completed_hours+$completed_hours)
WHERE user_id = {user_id} AND opportunity_id = {opportunity_id}
Could anyone help write this as a procedure or a trigger of some kind or help me in the right direction to get a starting point for looping over this stuff? Manually the querying works, just need to be looped / automatic for a stats update to run.
You can create a trigger to update hours_statistics whenever user_hours is updated (you may also want to add similar triggers for INSERT and DELETE operations, depending on your application logic).
Assuming that a UNIQUE key has been defined on hours_statistics.(user_id, opportunity_id) one can use INSERT ... ON DUPLICATE KEY UPDATE within the trigger:
CREATE TRIGGER foo AFTER UPDATE ON user_hours FOR EACH ROW
INSERT INTO hours_statistics (user_id, opportunity_id, completed_hours) VALUES
(OLD.user_id, OLD.opportunity_id, -OLD.completed_hours),
(NEW.user_id, NEW.opportunity_id, +NEW.completed_hours)
ON DUPLICATE KEY UPDATE
completed_hours = completed_hours + VALUES(completed_hours);
Then you can use a single UPDATE statement (using the multiple-table syntax to join user_hours with user_calendar) to perform all of the updates on user_hours in one go, which will cause the above trigger to update hours_statistics as desired:
UPDATE user_hours JOIN user_calendar USING (user_calendar_id, opportunity_id)
SET user_hours.completed_hours = agreed_hours,
user_hours.hours_committed = 'completed'
WHERE user_hours.hours_committed = 'accepted'
AND user_hours.completed_hours IS NULL
AND user_calendar.date_start = CURRENT_DATE();