I'm working on a software for managing the Rally company of my boss, where he can manage all the volunteers, their affectations, and many other things.
But the volunteers and these others things vary depending on the event, so they all have a column representing the event that they are linked/related to.
My boss requested that I add a "duplicate" button, that would duplicate an event (from my events table) and also duplicate all the volunteers, and values from any other table that is linked to that event, so the new duplications are linked to the new event.
The reason for this, is that he is constantly organizing rallies, and often it happens that the data from a Rally (event) to another is almost the same, so instead of adding it all manually, he'd rather make an entire duplication of the event and all the data related to it, then manually add and remove the errors in it.
I would like to know, is there any way in MySQL that I could duplicate an event, and everything that is linked to it's ID, even though they are in different tables, and make the duplications have the ID of the new event?
Sadly I don't have very much time, but until I get an answer I can work on other tasks my boss gave me.
Thank you so much to anybody who helps me or gives me any hint!!
EDIT:
Here's the schema of my Database (I know it's kinda dirty and there's issues with it, my boss gave me indications on how to create the database since he used to work in the domain before, but he didn't tell me how to make the links and he wants to make them himself)
And I apologize for the French language and the weird names..
Basically I wish to duplicate an entry in the "event" table, all the "affect" and "lieu" entries that are linked to it, and all the "tache" entries related the the duplicated "lieu" entries.
EDIT 2:
Thank you MrMadsen for the Query!
I had to fix it a bit, but here's what it looks like after.
SET #NEWEVEN = (SELECT MAX(NO_EVE) from db_rallye.event)+1;
INSERT INTO db_rallye.event
SELECT #NEWEVEN,
NM_EVE,
AN_EVE,
DT_EVE,
NM_REG_EVE
FROM event
WHERE NO_EVE = event_to_duplicate;
SET #NO_AFFECT_LIEU = (SELECT MAX(NO_AFF) from db_rallye.affect);
INSERT INTO db_rallye.affect
SELECT #NO_AFFECT_LIEU:=#NO_AFFECT_LIEU+1,
CO_AFF,
DT_AVI_AFF,
DS_STA_AFF,
CO_STA_AFF,
NO_BRA_EVN,
NO_PERS,
#NEWEVEN,
NO_EQU,
NO_LIE,
NO_PERS_RES,
IN_LUN,
IN_BAN,
DS_HEB,
IN_HEB_JEU,
IN_HEB_VEN,
IN_HEB_SAM,
NO_BOR,
NO_TUL_CAH,
NB_SPEC
FROM affect
WHERE NO_EVEN = event_to_duplicate;
INSERT INTO db_rallye.lieu
SELECT NO_LIE,
#NEWEVEN,
CO_LAT,
CO_LON,
FI_IMA,
FI_CRO,
FI_TUL,
DS_LIE,
DS_COU,
DS_LON,
NB_BLK,
VL_KM,
IN_FUS,
VL_DIS_FUS,
NO_LIE_FUS_SUI
FROM lieu
WHERE NO_EVEN = event_to_duplicate;
SET #NO_AFFECT_TACHE = (SELECT MAX(NO_TAC) from db_rallye.tache);
INSERT INTO db_rallye.tache
SELECT #NO_AFFECT_TACHE:=#NO_AFFECT_TACHE+1,
NO_LIE,
#NEWEVEN,
NO_AFF,
DS_REP,
DS_TAC
FROM tache
WHERE NO_LIE IN
(SELECT NO_LIE FROM lieu WHERE NO_EVEN = event_to_duplicate);
If a lot of the events contain similar information than I would create a template (or templates and the ability to create/modify templates) containing all of the information that you would duplicate.
Then when a new event is created he can just choose a starting template and then only add whatever data is unique to that event. In my opinion this would be much better than constantly duplicating the data.
As far as how to duplicate a row and all the associated rows, this is completely dependent on your database schema and how the tables relate to one another. If you post the relevant part of that we can help you more.
Edit
Here are the queries I came up with, test them in a dev database first but I think they will work. Let me know. Good luck!
INSERT INTO `event`
SELECT NULL NO_EVE,
NM_EVE,
AN_EVE,
DT_EVE,
NM_REG_EVE
FROM `email_log`
WHERE id NO_EVE = id_of_event_to_duplicate
INSERT INTO `affect`
SELECT NULL NO_AFF,
CO_AFF,
DT_AVI_AFF,
DS_STA_AFF,
CO_STA_AFF,
NO_BRA_EVN,
NO_PERS,
NO_EVEN,
NO_EQU,
NO_LIE,
NO_PERS_RES,
IN_LUN,
IN_BAN,
DS_HEB_JEU,
IN_HEB_VEN,
IN_HEB_SAM,
NO_BOR,
NO_TUL_CAH,
NB_SPEC
FROM `affect`
WHERE NO_EVE = id_of_event_to_duplicate
INSERT INTO `lieu`
SELECT NULL NO_LIE,
NO_EVEN,
CO_LAT,
CO_LON,
FI_IMA,
FI_CRO,
FI_TUL,
DS_LIE,
DS_COU,
DS_LON,
DB_BLK,
VL_KM,
IN_FUS,
VL_DIS_FUS,
NO_LIE_FUS_SUI
FROM `lieu`
WHERE NO_EVEN = id_of_event_to_duplicate
INSERT INTO `tache`
SELECT NULL NO_TAC,
NO_LIE,
NO_EVEN,
NO_AFF,
DS_REP,
DS_TAC
FROM `tache`
WHERE NO_LIE IN
(SELECT NO_LIE FROM `lieu` WHERE NO_EVEN = id_of_event_to_duplicate)
Basically I want to query a database and modify the values of one column based on the contents of another.
Here's my idea of how it would work:
IF Column 'Town' IS NOT NULL then Column 'Sign-up type' = 1 else = 0
The logic is, i've added a new column into the DB that will store whether a quick or full sign up has been made.
Quick = 0, Full = 1. Default is 0 = Quick.
I've managed to implement the change on the two registration forms that feed the DB, but I need to append the historical data to backwards fill the data.
Because the quick sign up only collects name, and email, those entries do not contain data in the 'Town' field which is a required field in a full sign up.
So i'm using that as a reference point to select all the entries that DO have (NOT NULL?) data in order to enter '1' (representing 'Full') into 'Signup Type' column.
I hope I'm making sense! I only have a basic understanding of MySQL but I'm willing to learn, it's sometimes hard trying to explain what I want to do when I'm unclear of the correct jargon!!
UPDATE yourTable SET signupType = IF(Town IS NULL, 1, 0);
Note this will update all data, you may want to limit this to historical data (by the sounds of things this should be fine however).
I'm writing a simple forum for a php site. I'm trying to calculate the post counts for each category. Now a category can belong to another category with root categories being defined as having a NULL parent_category_id. With this architecture a category can have an unlimited number of sub-categories and keeps the table structure fairly simple.
To keep things simple lets say the categories table has 3 fields: category_id, parent_category_id, post_count. I don't think the remaining database structure is relevant so I'll leave it out for now.
Another trigger is calling the categories table causing this trigger to run. What I want is it to update the post count and then recursively go through each parent category increasing that post count.
DELIMITER $$
CREATE TRIGGER trg_update_category_category_post_count BEFORE UPDATE ON categories FOR EACH ROW
BEGIN
IF OLD.post_count != NEW.post_count THEN
IF OLD.post_count < NEW.post_count THEN
UPDATE categories SET post_count = post_count + 1 WHERE categories.category_id = NEW.parent_category_id;
ELSEIF OLD.post_count > NEW.post_count THEN
UPDATE categories SET post_count = post_count - 1 WHERE categories.category_id = NEW.parent_category_id;
END IF;
END IF;
END $$
DELIMITER ;
The error I'm getting is:
#1442 - Can't update table 'categories' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
I figure you can do a count() on each page load to calculate the total posts but on large forums this will slow things down as discussed many times on here (e.g. Count posts with php or store in database). Therefore for future proofing i'm storing the post count in the table. To go one step further I thought i'd use triggers to update these counts rather than PHP.
I understand there are limitations in MySQL for running triggers on the same table that's being updated which is what is causing this error (i.e. to stop an infinite loop) but in this case surely the loop would stop once it reaches a category with a NULL parent_category_id? There must be some kind of solution whether it's adjusting this trigger or something different entirely. Thanks.
EDIT I appreciate this might not be the best way of doing things but it is the best thing I can think of. I suppose if you changed a parents category to another it would mess things up, but this could be fixed by another trigger which re-syncs everything. I'm open to other suggestions on how to solve this problem.
I usually recommend against using triggers unless you really, really need to; recursive triggers are a great way of introducing bugs that are really hard to reproduce, and require developers to understand the side effects of an apparently simple action - "all I did was insert a record into the categories table, and now the whole database has locked up". I've seen this happen several times - nobody did anything wrong or stupid, it's just a risk you run with side effects.
So, I would only resort to triggers once you can prove you need to; rather than relying on the opinion of strangers based on generalities, I'd rig up a test environment, drop in a few million test records, and try to optimize the "calculate posts on page load" solution so it works.
A database design that might help with that is Joe Celko's "nested set" schema - this takes a while to get your head round, but can be very fast for querying.
Only once you know you have a problem that you really can't solve other than by pre-computing the post count would I consider a trigger-based approach. I'd separate out the "post counts" into a separate table; that keeps your design a little cleaner, and should get round the recursive trigger issue.
The easiest solution is to fetch all the posts per category and afterwards link them together using a script/programming language:
for instance in php:
<?php
// category: id, parent, name
// posts: id, title, message
$sql = "select *, count(posts.id) From category left join posts ON posts.cat = category.id Group by category.id";
$query = mysql_query($sql);
$result = array();
while($row = mysql_fetch_assoc($query)){
$parent = $row['parent'] == null ? 0 : $row['parent'];
$result[$parent][] = $row;
}
recur_count(0);
var_dump($result);
function recur_count($depth){
global $result;
var_dump($result[$depth],$depth);
foreach($result[$depth] as $id => $o){
$count = $o['count'];
if(isset($result[$o['id']])){
$result[$depth][$id]['count'] += recur_count($o['id']);
}
}
return $count;
}
Ok so for anyone wondering how I solved this I used a mixture of both triggers and PHP.
Instead of getting each category to update it's parent, I've left it to the following structure: a post updates it's thread and then a thread updates it's category with the post count.
I've then used PHP to pull all categories from the database and loop through adding up each post count value using something like this:
function recursiveCategoryCount($categories)
{
$count = $categories['category']->post_count;
if(!is_null($categories['children']))
foreach($categories['children'] as $child)
$count += recursiveCategoryCount($child);
return $count;
}
At worst instead of PHP adding up every post on every page load, it only adds up the total category posts (depending at what node in the tree you are in). This should be very efficient as you're reducing the total calculations from 1000s to 10s or 100s depending on your number of categories. I would also recommend running a script every week to recalculate the post counts in case they become out of sync, much like phpBB. If I run into issues using triggers then I'll move that functionality into the code. Thanks for everyones suggestions.
We are trying to collect data on each person that used a certain coupon code "NEWCUSTOMER". We are trying to get the order details including their name, email address, and what they ordered.
Is the rule_id connected to an order in any way in the database? The magento databases don't seem to be all that friendly when you are trying to write your own mySQL statement to figure this information out.
Thanks!
This is similar to your previous question which i have also answered for you: Find the name and email address of non-members who used coupon code in Magento
The coupon code used on an order is actually a property of the order: coupon_code
It sounds from your question that you are directly querying the db, if so then you are looking for the coupon_code field in the sales_flat_order table.
Here is the sql:
SELECT `customer_firstname`, `customer_lastname`, `customer_email` FROM `sales_flat_order` WHERE `coupon_code` = 'your_awesome_coupon_code' AND `customer_group_id` = 0
Or, via magento...
$orderCollection = Mage::getModel('sales/order')->getCollection()
->addAttributeToSelect('customer_firstname')
->addAttributeToSelect('customer_lastname')
->addAttributeToSelect('customer_email')
->addAttributeToSelect('customer_group_id')
->addAttributeToSelect('coupon_code')
->addAttributeToFilter('customer_group_id', Mage_Customer_Model_Group::NOT_LOGGED_IN_ID)
->addAttributeToFilter('coupon_code', 'NEWCUSTOMER');
I am writing a query in a mysql db website and need a little help on the select statement syntax. I need to retrieve info from a database containing user input from a web-form at my site. There are a large number of over-the-road drivers who need to check in reporting their location with this form. The goal is to have a concise grid display table on the resulting web page that shows only the latest entry for all the drivers with only the 3 criteria on each row, (– name – location – date/time). The code included below does return results for all the drivers, but in the form of a long list of all entries for each driver on multiple pages instead of just updating location for each driver. It seems like I need to use “DISTINCT” and/or “LIMIT” in the string, but my attempts at this haven’t produced the desired results.
Thanks, Mike
$myquery = "select name, location, recordtime from ".$config->site_db."form_db order by recordtime DESC";
If I understand correctly you want to select the record with the highest recordtime for each name:
$myquery = "select name, location, max(recordtime) from ".$config->site_db."form_db group by name";