How can I do this MySQL Statements all in one? - mysql

I have a table with stocks and its prices. Moreover, I have all Rates in this table. Now I would like to get all MArketCAP in USD (= column MarketCap * FXRATE) for all stocks. The original MarketCAP column is in local currency. So I have to multiply by the latest rates.
To get the latetest rates I did following:
Table example:
DROP TABLE IF EXISTS `aktien`;
CREATE TABLE `aktien` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`dummyfield` varchar(255) DEFAULT NULL,
`Company` varchar(255) DEFAULT NULL,
`Stock_Short` varchar(50) DEFAULT NULL,
`country` varchar(10) DEFAULT 'US',
`LastPrice` decimal(17,3) DEFAULT NULL,
`PrevClose` decimal(17,3) DEFAULT NULL,
`PercChange` varchar(50) DEFAULT NULL,
`DayLow` decimal(17,3) DEFAULT NULL,
`DayHigh` decimal(17,3) DEFAULT NULL,
`Dividend` decimal(17,3) DEFAULT '0.000',
`ExDATE` datetime DEFAULT NULL,
`ImportDATE` datetime DEFAULT NULL,
`TradeDate` date DEFAULT NULL,
`refTradeDate` datetime DEFAULT NULL,
`timed` time DEFAULT NULL,
`Open` decimal(17,3) DEFAULT '0.000',
`AfterHrsChange` varchar(200) DEFAULT NULL,
`Volume` bigint(20) DEFAULT '0',
`AskSize` int(17) DEFAULT '0',
`BidSize` int(17) DEFAULT '0',
`AvgDayVol` bigint(20) DEFAULT '0',
`50DMA` decimal(17,3) DEFAULT '0.000',
`200DMA` decimal(17,3) DEFAULT '0.000',
`52WeekHigh` decimal(17,3) DEFAULT '0.000',
`52WeekLow` decimal(17,3) DEFAULT '0.000',
`52WeekRange` varchar(200) DEFAULT NULL,
`MarketCap` varchar(200) DEFAULT NULL,
`EPS` decimal(17,3) DEFAULT '0.000',
`BV` decimal(17,3) DEFAULT '0.000',
`EBITDA` varchar(200) DEFAULT NULL,
`P2S` decimal(17,3) DEFAULT '0.000',
`P2B` decimal(17,3) DEFAULT '0.000',
`PE` decimal(17,3) DEFAULT '0.000',
`Revenue` varchar(200) DEFAULT NULL,
`Mean10LastPrice` decimal(17,3) DEFAULT '0.000',
`Mean20LastPrice` decimal(17,3) DEFAULT '0.000',
`Mean50LastPrice` decimal(17,3) DEFAULT '0.000',
`Mean100LastPrice` decimal(17,3) DEFAULT '0.000',
`Mean200LastPrice` decimal(17,3) DEFAULT '0.000',
`NewHigh` int(1) DEFAULT '0',
`NewLow` int(1) DEFAULT '0',
`stocktype` varchar(50) DEFAULT 'stock',
`NormLastPrice` decimal(17,3) DEFAULT NULL,
`trendcode` int(1) DEFAULT '0',
`Todayflag` int(1) DEFAULT '0',
`KGVC` decimal(17,3) DEFAULT NULL,
`KGVN` decimal(17,3) DEFAULT NULL,
`ShortRatio` decimal(17,3) DEFAULT NULL,
`EPSC` decimal(17,3) DEFAULT NULL,
`EPSN` decimal(17,3) DEFAULT NULL,
`Target1Y` decimal(17,3) DEFAULT NULL,
`AdjClose` decimal(17,3) DEFAULT NULL,
`DMANote` varchar(60) DEFAULT '',
PRIMARY KEY (`id`),
UNIQUE KEY `Stock_Short` (`Stock_Short`,`TradeDate`)
) ENGINE=InnoDB AUTO_INCREMENT=1594308 DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = #saved_cs_client */;
--
-- Dumping data for table `aktien_stack`
--
LOCK TABLES `aktien` WRITE;
/*!40000 ALTER TABLE `aktien_stack` DISABLE KEYS */;
INSERT INTO `aktien` VALUES (1592307,NULL,'LUFTHANSA AG VNA
`O.N','LHA.DE','DE',25.110,24.290,'0.033758733',24.150,25.340,0.800,
'2018-05-09 00:00:00','2018-05-11 20:01:06',
'2018-05-11',NULL,NULL,24.270,NULL,4681038,1900800,948200,3320935,
25.694,27.756,31.260,16.095,NULL,'11862591488',0.000,0.000,
'5404000256',0.333,0.000,4.990,'35650998272',
24.739,25.517,26.056,27.511,26.004,0,0,'stock',
NULL,0,0,0.333,NULL,NULL,NULL,NULL,NULL,NULL,''),
(1592660,NULL,'EUR/USD','EURUSD=X','US',1.194,1.192,'0.0020306304',
1.190,1.197,NULL,NULL,'2018-05-11 23:00:03',
'2018-05-11',NULL,NULL,1.192,NULL,0,0,0,0,1.223,
1.209,1.256,1.086,NULL,NULL,0.000,0.000,NULL,NULL,
0.000,NULL,NULL,0.000,0.000,0.000,0.000,0.000,0,0,
'cur',NULL,0,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'')
/*!40000 ALTER TABLE `aktien_stack` ENABLE KEYS */;
UNLOCK TABLES;
How can I do the multiplication of all MarketCap by the FXRATE of all stocks (consider that LocalCurrencyCountry = country) in one statement?
I have done this way: ( I think it might be done with a temp table, right?)
drop table if exists rr;
create TEMPORARY TABLE rr
SELECT s.Stock_Short,
s.country,
rate.country as LocalCurrencyCountry,
s.PrevClose as FXRATE, TradeDate from
(select *,max(id) as maxid from aktien GROUP BY
TradeDate,Stock_short order by id desc) s
join rate on s.Stock_Short = rate.`code` where s.id = maxid
group by LocalCurrencyCountry order by TradeDate desc;
SELECT aktien.MarketCap * FXRATE ,rr.fxrate, Marketcap,
aktien.stock_short from aktien join rr on aktien.country =
rr.localcurrencyCountry group by aktien.country;

Here is my attempt at solving this, it contains 3 (!) sub-queries so its not pretty but maybe someone can optimise this.
The first sub-query is for selecting the "fx-rate" row for each country, the second one is for excluding the same "fx-rate" rows from the final result and the third one is to only include the latest market cap value
SELECT stock_short, marketCap * FX.rate, FX.country
FROM aktien a,
(SELECT PrevClose as rate, a3.country
FROM aktien a3 JOIN rate r ON a3.stock = r.code
ORDER BY tradeDate desc LIMIT 1) as FX
WHERE NOT EXISTS (SELECT * FROM rate WHERE code = a.stock)
AND tradeDate = (SELECT MAX(tradeDate) FROM aktien a2 WHERE a2.stock = a.stock)

You would need to do a select and a sub select. The subselect would select the key and MAX(TradeDate) grouped by the key. The outer select would join from that back to the tables on the trade date allowing you get the latest rate for each.
Generic example where the primary key is id, date. If you want specific to your tables please provide more information.
SELECT z.id, z.maxDate, t.rate
FROM (
SELECT id, MAX(date) AS maxDate
FROM table
GROUP BY id
) z
JOIN table t ON z.id=t.id AND z.maxDate=t.date

Related

MySQL - Why query does not sum same type of data if I use more left join?

My schema and sample data set:
CREATE TABLE `bsbi_hedge_fund` (
`id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
`fund_name` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
`abn_number` varchar(13) COLLATE utf8_unicode_ci DEFAULT NULL,
`parent_company_id` int(11) DEFAULT NULL,
`email` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
`contact_no` varchar(16) COLLATE utf8_unicode_ci DEFAULT NULL,
`address_one` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
`address_two` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
`city_name` varchar(60) COLLATE utf8_unicode_ci DEFAULT NULL,
`state_name` varchar(60) COLLATE utf8_unicode_ci DEFAULT NULL,
`zip_code` varchar(10) COLLATE utf8_unicode_ci DEFAULT NULL,
`country_tbl_id` int(11) DEFAULT NULL,
`status` varchar(10) COLLATE utf8_unicode_ci DEFAULT 'active',
`created_by` int(11) DEFAULT NULL,
`created_date` datetime DEFAULT NULL,
`modified_by` int(11) DEFAULT NULL,
`modified_date` datetime DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
--
-- Dumping data for table `bsbi_hedge_fund`
--
INSERT INTO `bsbi_hedge_fund` (`id`, `fund_name`, `abn_number`, `parent_company_id`, `email`, `contact_no`, `address_one`, `address_two`, `city_name`, `state_name`, `zip_code`, `country_tbl_id`, `status`, `created_by`, `created_date`, `modified_by`, `modified_date`) VALUES
(1, 'iCAP Hedge Funds', '53616271062', 1, 'icaptrading#gmail.com', '0425175887', '68 Roy Marika Street', '', 'Bonner', 'ACT', '2914', 12, 'active', 1, '2020-02-20 07:02:51', NULL, NULL);
CREATE TABLE `bsbi_company` (
`id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
`company_name` varchar(60) COLLATE utf8_unicode_ci DEFAULT NULL,
`abn_number` varchar(13) COLLATE utf8_unicode_ci DEFAULT NULL,
`acn_number` varchar(13) COLLATE utf8_unicode_ci DEFAULT NULL,
`email` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
`contact_no` varchar(16) COLLATE utf8_unicode_ci DEFAULT NULL,
`address_one` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
`address_two` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
`city_name` varchar(60) COLLATE utf8_unicode_ci DEFAULT NULL,
`state_name` varchar(60) COLLATE utf8_unicode_ci DEFAULT NULL,
`zip_code` varchar(10) COLLATE utf8_unicode_ci DEFAULT NULL,
`country_tbl_id` int(11) DEFAULT NULL,
`status` varchar(10) COLLATE utf8_unicode_ci DEFAULT 'active',
`created_by` int(11) DEFAULT NULL,
`created_date` datetime DEFAULT NULL,
`modified_by` int(11) DEFAULT NULL,
`modified_date` datetime DEFAULT NULL,
`allocated_money` float(17,5) DEFAULT '0.00000',
`hedge_fund_allocation` float(17,5) NOT NULL,
`investment_class_allocation` float(17,5) NOT NULL,
`hedge_fund_money` float(10,3) DEFAULT '0.000',
`inv_class_money` float(10,3) DEFAULT '0.000'
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
--
-- Dumping data for table `bsbi_company`
--
INSERT INTO `bsbi_company` (`id`, `company_name`, `abn_number`, `acn_number`, `email`, `contact_no`, `address_one`, `address_two`, `city_name`, `state_name`, `zip_code`, `country_tbl_id`, `status`, `created_by`, `created_date`, `modified_by`, `modified_date`, `allocated_money`, `hedge_fund_allocation`, `investment_class_allocation`, `hedge_fund_money`, `inv_class_money`) VALUES
(1, 'Investment and Capital Growth for Australian Professional ( ', '53616271062', '2123', 'abc#gmail.com', '2343', '68 Roy Marika Street', '', 'Bonner', 'ACT', '2914', 12, 'active', 1, '2020-02-20 07:01:26', 1, '2020-03-07 12:13:53', 22847.00000, 0.00000, 0.00000, 20000.000, 19000.000);
CREATE TABLE `bsbi_hedge_fund_journal` (
`id` int(11) NOT NULL,
`company_id` int(11) DEFAULT NULL,
`hedge_fund_id` int(11) DEFAULT NULL,
`amount` float(10,3) DEFAULT NULL,
`tran_type` varchar(7) COLLATE utf8_unicode_ci DEFAULT NULL,
`created_by` int(11) DEFAULT NULL,
`created_date` datetime DEFAULT NULL,
`modified_by` int(11) DEFAULT NULL,
`modified_date` datetime DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
--
-- Dumping data for table `bsbi_hedge_fund_journal`
--
INSERT INTO `bsbi_hedge_fund_journal` (`id`, `company_id`, `hedge_fund_id`, `amount`, `tran_type`, `created_by`, `created_date`, `modified_by`, `modified_date`) VALUES
(1, 1, 1, 20000.000, 'credit', 1, '2020-03-07 11:45:40', NULL, NULL);
CREATE TABLE `bsbi_investment_allocation_class_journal` (
`id` int(11) NOT NULL,
`hedge_fund_id` int(11) DEFAULT NULL,
`investment_class_id` int(11) DEFAULT NULL,
`amount` float(10,3) DEFAULT NULL,
`tran_type` varchar(7) COLLATE utf8_unicode_ci DEFAULT NULL,
`created_by` int(11) DEFAULT NULL,
`created_date` datetime DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
--
-- Dumping data for table `bsbi_investment_allocation_class_journal`
--
INSERT INTO `bsbi_investment_allocation_class_journal` (`id`, `hedge_fund_id`, `investment_class_id`, `amount`, `tran_type`, `created_by`, `created_date`) VALUES
(1, 1, 1, 18000.000, 'credit', 1, '2020-03-07 11:46:09'),
(2, 1, 1, 2000.000, 'credit', 1, '2020-03-07 12:12:02'),
(3, 1, 1, 1000.000, 'debit', 1, '2020-03-07 12:13:53');
...and fiddle of same ( http://sqlfiddle.com/#!9/9cd46d/2 ):
I have written the following query to fetch some data from the database:
SELECT
hf.*, com.company_name company_name, com.id com_id,
IFNULL( SUM( hfc.amount ), 0 ) hedge_credit, IFNULL( SUM( hfd.amount ), 0 ) hedge_debit,
IFNULL( SUM( cjc.amount ), 0 ) class_credit, IFNULL( SUM( cjd.amount ), 0 ) class_debit
FROM bsbi_hedge_fund hf
INNER JOIN bsbi_company com ON hf.parent_company_id = com.id
LEFT JOIN bsbi_hedge_fund_journal hfc ON (hfc.hedge_fund_id = hf.id AND hfc.tran_type='credit')
LEFT JOIN bsbi_hedge_fund_journal hfd ON ( hfd.hedge_fund_id = hf.id AND hfd.tran_type = 'debit' )
LEFT JOIN bsbi_investment_allocation_class_journal cjc ON (cjc.hedge_fund_id = hf.id AND cjc.tran_type = 'credit' )
LEFT JOIN bsbi_investment_allocation_class_journal cjd ON (cjd.hedge_fund_id = hf.id AND cjd.tran_type = 'debit' )
ORDER BY hf.id ASC
Here is the output of this query:
The problem I face is: hedge_credit value is 20000 but it shows 40000! similarly class_debit is 1000 but it shows 2000
After doing some R&D what I found is: bsbi_investment_allocation_class_journal table has two entry having tran_type = credit but for some unknown reason the following line of my query fetch two rows, rather sum the values (and I fear the same thing will happen to other left join if they also have more than one record of the same type!)
LEFT JOIN bsbi_investment_allocation_class_journal cjc ON (cjc.hedge_fund_id = hf.id AND cjc.tran_type = 'credit' )
If I add Group By clause to above query then I got:
Notice that class_credit has two different values that should sum up but does not sum for an unknown reason!!
Can anyone tell me what is actually wrong in my query that raises this issue?
- Thanks
Joins generate all possible combinations of rows that meet join criteria. Because you're using only hfc.hedge_fund_id = hf.id to join tables, you are duplicating rows. If there were three transactions in total, each would be tripled..
You'll need to select more data from the tables containing transactions to keep the rows unique: timestamps or transaction ids. I would usually select the unique rows that I want first, then left join the non-unique data (name, country, etc) to each row.
I got the solution from this: https://dba.stackexchange.com/questions/154586/sum-over-distinct-rows-with-multiple-joins
If someone faces the exact type of problem then they can check this solution: https://dba.stackexchange.com/questions/154586/sum-over-distinct-rows-with-multiple-joins

Filtering results in MySQL in join result

I am beginner programmer. I have small problem with my MySQL Queries.
This is my MySQL data: https://pastebin.com/69PcBSVH
I have this tables:
CREATE TABLE `dishes` (
`id` bigint(20) UNSIGNED NOT NULL,
`company_id` bigint(20) UNSIGNED NOT NULL,
`name` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`description` longtext COLLATE utf8mb4_unicode_ci,
`enable` char(1) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '1',
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `dish_values` (
`id` bigint(20) UNSIGNED NOT NULL,
`dishes_id` bigint(20) UNSIGNED NOT NULL,
`food_ingredient_id` bigint(20) UNSIGNED NOT NULL,
`company_id` bigint(20) UNSIGNED NOT NULL,
`quantity` decimal(9,2) NOT NULL DEFAULT '0.00'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `food_ingredients` (
`id` bigint(20) UNSIGNED NOT NULL,
`company_id` bigint(20) UNSIGNED NOT NULL,
`name` varchar(120) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`garbage` decimal(9,2) NOT NULL DEFAULT '0.00',
`energy_value` decimal(9,2) NOT NULL DEFAULT '0.00',
`protein` decimal(9,2) NOT NULL DEFAULT '0.00',
`fat` decimal(9,2) NOT NULL DEFAULT '0.00',
`available_carbohydrates` decimal(9,2) NOT NULL DEFAULT '0.00',
`roughage` decimal(9,2) NOT NULL DEFAULT '0.00',
`description` longtext COLLATE utf8mb4_unicode_ci,
`url_address` varchar(160) COLLATE utf8mb4_unicode_ci NOT NULL,
`allergen` char(1) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0',
`allergen1` char(1) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0',
`allergen2` char(1) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0',
`allergen3` char(1) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0',
`available_in_demo` char(1) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0',
`enable` char(1) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '1'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
My base is a base of dishes and ingredients needed to prepare a dish.
I need to display all dishes that are not allergens (food_ingredients.allergen = 0).
Table dishes = given dishes
Table dish_values = ingredients that are assigned to a given dish
Food_ingredients table = ingredients of the dish.
Dishes that are allergens have a value of 1 in the allergen column and those that are not allergens 0.
I make query to show my dish (without allergens):
SELECT
dishes.id, dishes.company_id, dishes.name, dishes.description, dishes.enable
FROM `dishes` join dish_values on dish_values.dishes_id = dishes.id
join food_ingredients on food_ingredients.id = dish_values.food_ingredient_id
WHERE food_ingredients.allergen = 0
GROUP BY dishes.id
But it's not working correct.
As a result, I have both dishes that contain allergens and those that do not have them.
How can I repair it?
I would use not’exists with a correlated subquery: this avoids the need for aggregation, which is generally not good for performance on large datasets:
select d.*
from dishes d
where not exists (
select 1
from dish_values v
inner join food_ingredients i on i.id = v.food_ingredient_id
where
v.dishes_id = d.id
and i.allergen = 1
)
For performance, you want the following index: food_ingredients(allergen, id).
Side note: you should change the data type of allergen from char(1) to tinyint(1) since it only contains 0/1 values.
As allergen is a char column, you need quotes around the 0. Alternatively, you can change the column to an int.
Remove the WHERE clause and add the condition to the HAVING clause:
SELECT d.id, d.company_id, d.name, d.description, d.enable
FROM dishes d
INNER JOIN dish_values v ON v.dishes_id = d.id
INNER JOIN food_ingredients i ON i.id = v.food_ingredient_id
GROUP BY d.id, d.company_id, d.name, d.description, d.enable
HAVING SUM(i.allergen) = 0
The condition SUM(i.allergen) = 0 makes sure that all matching rows from the table food_ingredients have i.allergen = 0.

How to fetch related data between these two tables

I have got two tables by name pricechangeimpwl and suppourtimpwl
The two tables contain name in common .
This is my schema
CREATE TABLE IF NOT EXISTS `pricechangeimpwl` (
`name` varchar(100) DEFAULT NULL,
`p1` decimal(10,2) DEFAULT NULL,
`time1` varchar(100) DEFAULT NULL,
`p2` decimal(10,2) DEFAULT NULL,
`time2` varchar(100) DEFAULT NULL,
`whatnext` varchar(50) DEFAULT NULL,
`stock_low` decimal(6,2) DEFAULT NULL,
`buy_sell_diff` varchar(100) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO `pricechangeimpwl` (`name`, `p1`, `time1`, `p2`, `time2`, `whatnext`, `stock_low`, `buy_sell_diff`) VALUES
('DIVISLAB', 631.75, '2017-03-21 15:29:09', 630.85, '2017-03-21 15:40:47', 'plzcontinue', 628.60, '-417055'),
('M&M', 1297.00, '2017-03-21 15:29:09', 1299.00, '2017-03-21 15:40:47', 'plzcontinue', 1271.00, '9190');
-- Dumping structure for table trade_chit_chat.suppourtimpwl
CREATE TABLE IF NOT EXISTS `suppourtimpwl` (
`name` varchar(100) DEFAULT NULL,
`suppourt1` decimal(10,2) DEFAULT NULL,
`suppourt2` decimal(10,2) DEFAULT NULL,
`suppourt3` decimal(10,2) DEFAULT NULL,
`date` varchar(100) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO `suppourtimpwl` (`name`, `suppourt1`, `suppourt2`, `suppourt3`, `date`) VALUES
('DIVISLAB', 762.54, 752.68, 739.35, '20 March 2017'),
('M&M', 1292.25, 1284.30, 1273.41, '20 March 2017');
This is my sql fiddle
http://sqlfiddle.com/#!9/0a9476/1
Can we write a select query so that it will fetch suppourt1 , suppourt2 and suppourt3 values for each symbol of pricechangeimpwl ??
select * from pricechangeimpwl p JOIN suppourtimpwl s
on p.name = s.name;

MySql Trigger: can't retrieve one specific column from NEW in after insert trigger

I have 3 tables:
pp088_project_tasks
CREATE TABLE IF NOT EXISTS `pp088_project_tasks` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`task_list_id` int(10) unsigned DEFAULT NULL,
`text` text CHARACTER SET utf8 COLLATE utf8_unicode_ci,
`start_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`due_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`assigned_to_company_id` int(10) DEFAULT NULL,
`assigned_to_user_id` int(10) unsigned DEFAULT NULL,
`completed_on` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`completed_by_id` int(10) unsigned DEFAULT NULL,
`created_on` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`created_by_id` int(10) unsigned DEFAULT NULL,
`updated_on` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`updated_by_id` int(10) unsigned DEFAULT NULL,
`order` int(10) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `task_list_id` (`task_list_id`),
KEY `completed_on` (`completed_on`),
KEY `created_on` (`created_on`),
KEY `order` (`order`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=76 ;
pp088_project_task_lists
CREATE TABLE IF NOT EXISTS `pp088_project_task_lists` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`milestone_id` int(10) unsigned NOT NULL DEFAULT '0',
`project_id` int(10) unsigned DEFAULT NULL,
`name` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
`priority` int(3) unsigned NOT NULL DEFAULT '0',
`description` text CHARACTER SET utf8 COLLATE utf8_unicode_ci,
`start_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`due_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`score` int(3) unsigned NOT NULL DEFAULT '0',
`is_private` tinyint(1) unsigned NOT NULL DEFAULT '0',
`completed_on` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`completed_by_id` int(10) unsigned DEFAULT NULL,
`created_on` datetime DEFAULT NULL,
`created_by_id` int(10) unsigned NOT NULL DEFAULT '0',
`updated_on` datetime DEFAULT NULL,
`updated_by_id` int(10) unsigned NOT NULL DEFAULT '0',
`order` tinyint(3) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `milestone_id` (`milestone_id`),
KEY `project_id` (`project_id`),
KEY `completed_on` (`completed_on`),
KEY `created_on` (`created_on`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ;
gantt_tasks
CREATE TABLE IF NOT EXISTS `gantt_tasks` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`text` varchar(255) NOT NULL,
`start_date` date NOT NULL,
`duration` int(11) NOT NULL,
`progress` float NOT NULL DEFAULT '1',
`sortorder` int(11) NOT NULL,
`parent` int(11) NOT NULL,
`projectID` int(10) unsigned DEFAULT NULL,
`tipo_evento` varchar(100) NOT NULL,
`idPier` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=48 ;
I created an AFTER INSERT trigger on the 'pp088_project_tasks' table to insert into 'gantt_tasks'
CREATE TRIGGER `insert_gantt_task` AFTER INSERT ON `pp088_project_tasks`
FOR EACH ROW BEGIN
declare project_id int;
declare duracion int;
set project_id=(select project_id from pp088_project_task_lists where id=NEW.task_list_id);
set duracion=(select DATEDIFF(NEW.due_date,NEW.start_date));
insert into gantt_tasks (text,start_date,duration,projectID,idPier) values (NEW.text,NEW.start_date,duracion,project_id,NEW.id);
END
but the problem is with the setting of the project_id variable which sets the gantt_tasks field projectID to NULL because that query cannot retrieve the value using NEW.task_list_id, even if I use that value directly on the insert just to check the value it sets the gantt_tasks field projectID to 0......The strange thing is that if I use other values of the NEW they all work, it's just that field, the insert is successful for all of the other fields on gantt_tasks. I checked and the types are the same, and so the collation as well.
The first two tables are from a project manager called projectPier and the gantt_tasks table is one I created for a gantt chart(DHTMLX gantt chart).
... but the problem is with the setting of the project_id variable which sets the gantt_tasks field projectID to NULL because that query cannot retrieve the value using NEW.task_list_id, even if I use that value directly on the insert just to check the value it sets the gantt_tasks field projectID to 0
Reason is very much visible.
You have a variable project_id whose name matches that of a column in the table.
And when you use column name without a table qualifier, there arises a conflict on the names. And priority will be given to the local variable over column.
In your case, due to the statement
declare project_id int;
the default value of project_id would be zero. And hence, the output of the statement
set project_id=(select project_id from pp088_project_task_lists
where id=NEW.task_list_id);
would be a zero. And hence the same is used in the insert statement.
Options:
Change local variable name to something relevant.
Use table name to qualify the column name.
Sample Example: (using option 1)
Make following changes to your code and it should be working.
delimiter //
CREATE TRIGGER `insert_gantt_task` AFTER INSERT ON `pp088_project_tasks`
FOR EACH ROW BEGIN
declare _project_id int default 0;
declare _duracion int default 0;
select project_id into _project_id
from pp088_project_task_lists
where id = NEW.task_list_id;
select DATEDIFF( NEW.due_date, NEW.start_date ) into _duracion;
insert into gantt_tasks ( text, start_date, duration, projectID, idPier )
values( NEW.text, NEW.start_date, _duracion, _project_id, NEW.id );
END;
//
delimiter ;
Sample Example: (using option 2)
Make following changes to your code and it should be working.
delimiter //
CREATE TRIGGER `insert_gantt_task` AFTER INSERT ON `pp088_project_tasks`
FOR EACH ROW BEGIN
declare project_id int default 0;
declare duracion int default 0;
set project_id := ( select tl.project_id
from pp088_project_task_lists tl
where tl.id = NEW.task_list_id );
set duracion := select DATEDIFF( NEW.due_date, NEW.start_date );
insert into gantt_tasks ( text, start_date, duration, projectID, idPier )
values( NEW.text, NEW.start_date, duracion, project_id, NEW.id );
END;
//
delimiter ;

Slow update of one table when comparing multiple fields across two tables

The following query is timing out after 600 seconds.
update placed p
,Results r
set p.position = r.position
where p.competitor = r.competitor
AND p.date = r.date
AND REPLACE(p.time,":","") = r.time;
The structure is as follows:
'CREATE TABLE `placed` (
`idplaced` varchar(50) DEFAULT NULL,
`date` decimal(8,0) DEFAULT NULL,
`time` varchar(45) DEFAULT NULL,
`field1` varchar(45) DEFAULT NULL,
`competitor` varchar(45) DEFAULT NULL,
`field2` int(2) DEFAULT NULL,
`field3` varchar(45) DEFAULT NULL,
`field4` varchar(45) DEFAULT NULL,
`field5` decimal(6,2) DEFAULT NULL,
`field6` decimal(10,2) DEFAULT NULL,
`field7` decimal(6,2) DEFAULT NULL,
`field8` char(1) DEFAULT NULL,
`field9` varchar(45) DEFAULT NULL,
`position` char(4) DEFAULT NULL,
`field10` decimal(6,2) DEFAULT NULL,
`field11` char(1) DEFAULT NULL,
`field12` char(1) DEFAULT NULL,
`field13` decimal(6,2) DEFAULT NULL,
`field14` decimal(6,2) DEFAULT NULL,
`field15` decimal(6,2) DEFAULT NULL,
`field16` decimal(6,2) DEFAULT NULL,
`field17` decimal(6,2) DEFAULT NULL,
`field18` char(1) DEFAULT NULL,
`field19` char(20) DEFAULT NULL,
`field20` char(1) DEFAULT NULL,
`field21` char(5) DEFAULT NULL,
`field22` char(5) DEFAULT NULL,
`field23` int(11) DEFAULT NULL
PRIMARY KEY (`idplaced`),
UNIQUE KEY `date_time_competitor_field18_combo` (`date`,`time`,`competitor`,`field18`)
) ENGINE=InnoDB AUTO_INCREMENT=100688607 DEFAULT CHARSET=latin1;
CREATE TABLE `results` (
`idresults` int(11) NOT NULL AUTO_INCREMENT,
`date` char(8) DEFAULT NULL,
`time` char(4) DEFAULT NULL,
`field1` varchar(45) DEFAULT NULL,
`competitor` varchar(45) DEFAULT NULL,
`position` char(4) DEFAULT NULL,
`field2` varchar(45) DEFAULT NULL,
`field3` decimal(2,0) DEFAULT NULL,
PRIMARY KEY (`idresults`)
) ENGINE=InnoDB AUTO_INCREMENT=6644 DEFAULT CHARSET=latin1;
The PLACED table has 65,000 records, the RESULTS table has 9,000 records.
I am assuming the solution involves a JOIN statement of some descript, and I have tried taking several suggestions from this site, but am simply not finding the answer I am looking for. Simply put, I would be grateful for suggestions on this. I can put up example tables / create table code if requried.
The index cannot be used efficiently to perform the join because of your REPLACE operation.
I'd suggest creating an index with the columns in the following slightly different order:
(date, competitor, time, position)
It may also help to add this index on both tables.
It would be even better if you could modify the data in the database so that the data in the time column was stored in the same format in both tables.
First of all, you'd better send us your full tables description, using
show create table
Second, you'd better use join syntax :
update placed p
join Results r on r.competitor = p.competitor
set p.position = r.position
where p.date = r.date
AND REPLACE(p.time,":","") = r.time;
Hope this will help.