Related
As requested by #Adyson, I've added my database sample below.
CREATE TABLE test.patients ( id BIGINT NOT NULL AUTO_INCREMENT , branchID INT NOT NULL , patientNo VARCHAR(20) NOT NULL , billingAccounts VARCHAR(50) NOT NULL , firstName VARCHAR(20) NOT NULL , lastName VARCHAR(20) NOT NULL , PRIMARY KEY (id)) ENGINE = InnoDB;
INSERT INTO `patients` (`id`, `branchID`, `patientNo`, `billingAccounts`, `firstName`, `lastName`) VALUES (NULL, '1', 'PN017830', '[\"-1\",\"-2\",\"7632\",\"7774\"]', 'John', 'Daka'), (NULL, '1', 'PN017890', '[\"-1\",\"-2\",\"8120\",\"7742\"]', 'Ann', 'Mikail')
CREATE TABLE `test`.`products` ( `id` INT NOT NULL AUTO_INCREMENT , `type` ENUM('pharmaceutical','other') NOT NULL , `productCode` VARCHAR(50) NOT NULL , `brand` VARCHAR(50) NOT NULL , `manufacturer` INT NOT NULL , `generics` TEXT NOT NULL , `privateBranchID` INT NOT NULL , `regID` INT NOT NULL , `regDate` DATETIME NOT NULL , `status` ENUM('active','deactivated') NOT NULL , PRIMARY KEY (`id`)) ENGINE = InnoDB;
INSERT INTO `products` (`id`, `type`, `productCode`, `brand`, `manufacturer`, `generics`, `privateBranchID`, `regBy`, `regDate`, `status`) VALUES (10, 'pharmaceutical', '500015806877', 'gaviscon', '217', '[\"magaldrate\",\"simethicone\"]', '0', '1', CURRENT_TIMESTAMP, 'active'), (11, 'pharmaceutical', '7640153080325', 'lofral', '199', '[\"amlodipine\"]', '0', '1', CURRENT_TIMESTAMP, 'active')
CREATE TABLE `test`.productdiscounts ( `id` BIGINT NOT NULL AUTO_INCREMENT , `branchID` INT NOT NULL , `productID` BIGINT NOT NULL , `accountID` BIGINT NOT NULL , `discount` DECIMAL NOT NULL , `isActive` ENUM('1','0') NOT NULL , `regBy` INT NOT NULL , `regTimestamp` DATETIME on update CURRENT_TIMESTAMP NOT NULL , PRIMARY KEY (`id`)) ENGINE = InnoDB;
INSERT INTO `productdiscounts` (`branchID`, `productID`, `accountID`, `discount`, `isActive`, `regBy`, `regTimestamp`) VALUES ('1', '10', '7723', '90', '1', '1', '2022-08-25 08:01:59'), ('1', '10', '7724', '70', '1', '1', '2022-08-25 08:01:59'), ('1', '10', '-2', '70', '1', '1', '2022-08-25 08:01:59'), ('1', '10', '7720', '55', '1', '1', '2022-08-25 08:01:59')
CREATE TABLE chms.patients ( id BIGINT NOT NULL AUTO_INCREMENT , branchID INT NOT NULL , patientNo VARCHAR(20) NOT NULL , billingAccounts VARCHAR(50) NOT NULL , firstName VARCHAR(20) NOT NULL , lastName VARCHAR(20) NOT NULL , PRIMARY KEY (id)) ENGINE = InnoDB;
INSERT INTO patients (id, branchID, patientNo, billingAccounts, firstName, lastName) VALUES (NULL, '1', 'PN017830', '["-1","-2","7632","7774"]', 'John', 'Daka'), (NULL, '1', 'PN017890', '["-1","-2","8120","7742"]', 'Ann', 'Mikail')
CREATE TABLE test.products ( id INT NOT NULL AUTO_INCREMENT , type ENUM('pharmaceutical','other') NOT NULL , productCode VARCHAR(50) NOT NULL , brand VARCHAR(50) NOT NULL , manufacturer INT NOT NULL , generics TEXT NOT NULL , privateBranchID INT NOT NULL , regID INT NOT NULL , regDate DATETIME NOT NULL , status ENUM('active','deactivated') NOT NULL , PRIMARY KEY (id)) ENGINE = InnoDB;
INSERT INTO products (id, type, productCode, brand, manufacturer, generics, privateBranchID, regBy, regDate, status) VALUES (10, 'pharmaceutical', '500015806877', 'gaviscon', '217', '["magaldrate","simethicone"]', '0', '1', CURRENT_TIMESTAMP, 'active'), (11, 'pharmaceutical', '7640153080325', 'lofral', '199', '["amlodipine"]', '0', '1', CURRENT_TIMESTAMP, 'active')
CREATE TABLE test.productdiscounts ( id BIGINT NOT NULL AUTO_INCREMENT , branchID INT NOT NULL , productID BIGINT NOT NULL , accountID BIGINT NOT NULL , discount DECIMAL NOT NULL , isActive ENUM('1','0') NOT NULL , regBy INT NOT NULL , regTimestamp DATETIME on update CURRENT_TIMESTAMP NOT NULL , PRIMARY KEY (id)) ENGINE = InnoDB;
INSERT INTO productdiscounts (branchID, productID, accountID, discount, isActive, regBy, regTimestamp) VALUES ('1', '10', '7723', '90', '1', '1', '2022-08-25 08:01:59'), ('1', '10', '7724', '70', '1', '1', '2022-08-25 08:01:59'), ('1', '10', '-2', '70', '1', '1', '2022-08-25 08:01:59'), ('1', '10', '7720', '55', '1', '1', '2022-08-25 08:01:59')
This is my PHP code:
$searchSQL="
select
distinct
products.id,
products.type as productType,
products.brand,
products.status,
products.productCode,
products.generics,
coalesce((select discount from productdiscounts where(productID=products.id and branchID=1 and isActive='1' and patients.billingAccounts like concat('%\"',productdiscounts.accountID,'\"%')) order by discount desc limit 1),0.00) as discount,
concat('[',(select group_concat('{\"productID\":\"',productdiscounts.productID,'\",\"accountID\":\"',productdiscounts.accountID,'\",\"discount\":\"',productdiscounts.discount,'\",\"accountName\":\"',accounts.name,'\",\"accountNo\":\"',accounts.accountNo,'\"}') from productdiscounts
left join accounts on(productdiscounts.accountID=accounts.id)
where(productdiscounts.productID=products.id and productdiscounts.branchID = 1 and productdiscounts.isActive = '1' )),']') as allDiscounts
from products
left join stock on (products.id=stock.productID)
left join pricetags on (stock.priceTag=pricetags.id)
left join countries on (products.manufacturer=countries.id)
left join diagnosis on (diagnosis.diagnosisRef='')
left join patients on (patients.id=10)
where(
products.productCode='' or
products.generics like concat('%\"','magaldrate','%\"%') or
products.brand like concat('% ','gaviscon','%')
and (stock.isActive='1' and products.status='active')
)
order by products.brand limit 30
";
$productsQ=(new DB)->getRef()->prepare($searchSQL);
$productsQ->execute([]]);
$productsD=$productsQ->fetchAll();
I have a column (billingAccounts) that stores data as JSON Array like this: ["-1","-2","7632","7774"]
and in the product-discount table, I have rows for each company's discount and to get the discount, I use the below code but is a bit slow:
[enter image description here][1]
select products.brand, coalesce((select discount from productdiscounts where(productID=products.id and branchID=? and isActive='1' and patients.billingAccounts like concat('%"',productdiscounts.accountID,'"%')) order by discount desc limit 1),0.00) as discount
from products
left join patients on (patients.patientNo=diagnosis.patientNo)
.....
ALL I WANT IS TO RETURN THE MAXIMUM DISCOUNT FROM THE company ACCOUNTS THAT HAVE DISCOUNT ON THE PRODUCT AND ALSO MATCHES IN THE PATIENT BILLING ACCOUNS.
Note: I don't want to use concat or group_concat because is what I'm currently using and it's making the query to be slow!
This is my SQL table and data. http://sqlfiddle.com/#!9/effe2
CREATE TABLE IF NOT EXISTS `CustomValue` (
`id` int(11) NOT NULL,
`customFieldId` int(11) NOT NULL,
`relatedId` int(11) NOT NULL,
`fieldValue` text COLLATE utf8_unicode_ci,
`createdAt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=MyISAM AUTO_INCREMENT=8 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
INSERT INTO `CustomValue` (`id`, `customFieldId`, `relatedId`, `fieldValue`, `createdAt`) VALUES
(1, 10, 4031, NULL, '2015-11-05 04:25:00'),
(2, 14, 4031, 'adsas#das.sadsa', '2015-11-05 04:25:00'),
(3, 13, 4031, '456', '2015-11-05 04:25:00'),
(4, 16, 4031, '2015-11-09', '2015-11-05 04:25:00'),
(5, 9, 4031, '456', '2015-11-05 04:25:00'),
(6, 11, 4031, 'dsasda', '2015-11-05 04:25:00'),
(7, 15, 4031, '1', '2015-11-05 04:25:00');
Right now it is as,
id customFieldId relatedId fieldValue createdAt
1 10 4031 (null) November, 05 2015 04:25:00
2 14 4031 adsas#das.sadsa November, 05 2015 04:25:00
3 13 4031 456 November, 05 2015 04:25:00
4 16 4031 2015-11-09 November, 05 2015 04:25:00
5 9 4031 456 November, 05 2015 04:25:00
6 11 4031 dsasda November, 05 2015 04:25:00
7 15 4031 1 November, 05 2015 04:25:00
I need to group by relatedId and and get the final output as 1 row for each relatedId.
This is the reference table.
CREATE TABLE IF NOT EXISTS `CustomField` (
`id` int(11) NOT NULL,
`customTypeId` int(11) NOT NULL,
`fieldName` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
`relatedTable` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
`defaultValue` text COLLATE utf8_unicode_ci,
`sortOrder` int(11) NOT NULL DEFAULT '0',
`enabled` char(1) COLLATE utf8_unicode_ci DEFAULT '1',
`listItemTag` char(1) COLLATE utf8_unicode_ci DEFAULT NULL,
`required` char(1) COLLATE utf8_unicode_ci DEFAULT '0',
`onCreate` char(1) COLLATE utf8_unicode_ci DEFAULT '1',
`onEdit` char(1) COLLATE utf8_unicode_ci DEFAULT '1',
`onView` char(1) COLLATE utf8_unicode_ci DEFAULT '1',
`listValues` text COLLATE utf8_unicode_ci,
`label` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
`htmlOptions` text COLLATE utf8_unicode_ci
) ENGINE=MyISAM AUTO_INCREMENT=17 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
INSERT INTO `CustomField` (`id`, `customTypeId`, `fieldName`, `relatedTable`, `defaultValue`, `sortOrder`, `enabled`, `listItemTag`, `required`, `onCreate`, `onEdit`, `onView`, `listValues`, `label`, `htmlOptions`) VALUES
(13, 1, 'HOMEEMAIL', 'people', '', 0, '1', NULL, '1', '1', '1', '1', NULL, 'Home Email', ''),
(9, 1, 'LANDPHONENO', 'people', '', 0, '1', NULL, '1', '1', '1', '1', NULL, 'Land Phone No', ''),
(10, 12, 'ABOUTME', 'people', '', 0, '1', NULL, '0', '1', '1', '1', NULL, 'About Me', ''),
(11, 3, 'PHONENUMBER2', 'people', '', 0, '1', NULL, '1', '1', '1', '1', NULL, 'Phone Number 2', ''),
(14, 3, 'ALTERNATEEMAIL', 'people', '', 0, '1', NULL, '1', '1', '1', '1', NULL, 'Alternate Email', ''),
(15, 11, 'SCHOOLING?', 'people', '', 0, '1', NULL, '1', '1', '1', '1', NULL, 'Schooling?', ''),
(16, 4, 'JOINDATE', 'people', '', 0, '1', NULL, '1', '1', '1', '1', NULL, 'Join Date', '');
The final output should be,
relatedId | Alternate Email | Home Email | Join Date | Land Phone No | Phone Number 2 | Schooling?
--------------------------------------------------------------------------------------------------
4031 | adsas#das.sadsa | 456 | 2015-11-09| 456 | dsasda | 1
relatedId | Alternate Email | Home Email | Join Date | Land Phone No | Phone Number 2 | Schooling? | Interest
--------------------------------------------------------------------------------------------------
4033 | adsas#das.sadsa | 456 | 2015-11-09| 456 | dsasda | 1 | Drawing
The output of phpmyadmin
What you need here is PIVOT rows into columns, MySQL however doesn't have a native pivot operator like SQL Server or Oracle for example. But you can use CASE expression with group by to do this like this:
SELECT
v.relatedId, v.CreatedAt,
MAX(IF(f.fieldName = 'ABOUTME', COALESCE(v.fieldValue, f.defaultValue) , NULL)) AS 'ABOUTME',
MAX(IF(f.fieldName = 'ALTERNATEEMAIL', COALESCE(v.fieldValue, f.defaultValue) , NULL)) AS 'ALTERNATEEMAIL',
MAX(IF(f.fieldName = 'HOMEEMAIL', COALESCE(v.fieldValue, f.defaultValue) , NULL)) AS 'HOMEEMAIL',
MAX(IF(f.fieldName = 'JOINDATE', COALESCE(v.fieldValue, f.defaultValue) , NULL)) AS 'JOINDATE',
MAX(IF(f.fieldName = 'LANDPHONENO', COALESCE(v.fieldValue, f.defaultValue) , NULL)) AS 'LANDPHONENO',
MAX(IF(f.fieldName = 'PHONENUMBER2', COALESCE(v.fieldValue, f.defaultValue) , NULL)) AS 'PHONENUMBER2',
MAX(IF(f.fieldName = 'SCHOOLING?', COALESCE(v.fieldValue, f.defaultValue) , NULL)) AS 'SCHOOLING?'
FROM customField AS f
INNER JOIN Customvalue AS v ON f.Id = v.customFieldId
GROUP BY v.relatedId, v.CreatedAt;
And to do it dynamically you have to do it with dynamic sql like this:
SET #Colvalues = NULL;
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT CONCAT('MAX(IF(f.fieldName = ''',
f.fieldName, ''', COALESCE(v.fieldValue, f.defaultValue) , NULL)) AS ', '''', f.fieldName , '''')
) INTO #Colvalues
FROM customField AS f
INNER JOIN Customvalue AS v ON f.Id = v.customFieldId;
SET #sql = CONCAT('SELECT
v.relatedId, v.CreatedAt, ', #Colvalues , '
FROM customField AS f
INNER JOIN Customvalue AS v ON f.Id = v.customFieldId
GROUP BY v.relatedId, v.CreatedAt;');
PREPARE stmt
FROM #sql;
EXECUTE stmt;
Note that:
If the field value is null it will set the value from the default value field, thats what COALESCE(v.fieldValue, f.defaultValue) do.
You can eliminate NULL values like in the field Aboutname case, by adding a WHERE v.fieldValue IS NOT NULL.
This will give you:
I'm trying to import a csv to a mysql table in my db but I keep getting this error:
Unknown column '' in 'field list'
INSERT INTO `job_budget_report` (`Job_Num`, `Description`, `EngWeekly`, `EngTTD`, `EngBudget`, `DesignWeekly`, `DesignTTD`, `DesignBudget`, `DetailsWeekly`, `DetailsTTD`, `DetailsBudget`, `EjectionWeekly`, `EjectionTTD`, `EjectionBudget`, `CarbonEDMWeekly`, `CarbonEDMTTD`, `CarbonEDMBudget`, `GdrillBMWeekly`, `GdrillBMTTD`, `GdrillBMBudget`, `CNCWeekly`, `CNCTTD`, `CNCBudget`, `MMQCOtherWeekly`, `MMQCOtherTTD`, `MMQCOtherBudget`, `SpottingWeekly`, `SpottingTTD`, `SpottingBudget`, `SpotPLWeekly`, `SpotPLTTD`, `SpotPLBudget`, `HWWeekly`, `HWTTD`, `HWBudget`, `TotalMach`, `TotalOther`, `TotalOFMach`, ``) VALUES
('1000', 'description text here', '0', '0', '0', NULL, '0', '0', NULL, NULL, '0', NULL, '0', NULL, '0', '0', '0', '0', '0', '0', '0', '0', '0', '20.5', '0', '0', '0', '0', '0', '18.5', '40', '0', '0', '0', '0', '0', '0', '0', '');
Table Structure:
http://imgur.com/rFLw4c7
Now I realize that theres extra empty fields in that query but how do I remove them from my csv ?
Here's what my csv looks like when I open it in sublime text:
Job_Num;Description;EngWeekly;EngTTD;EngBudget;DesignWeekly;DesignTTD;DesignBudget;DetailsWeekly;DetailsTTD;DetailsBudget;EjectionWeekly;EjectionTTD;EjectionBudget;CarbonEDMWeekly;CarbonEDMTTD;CarbonEDMBudget;GdrillBMWeekly;GdrillBMTTD;GdrillBMBudget;CNCWeekly;CNCTTD;CNCBudget;MMQCOtherWeekly;MMQCOtherTTD;MMQCOtherBudget;SpottingWeekly;SpottingTTD;SpottingBudget;SpotPLWeekly;SpotPLTTD;SpotPLBudget;HWWeekly;HWTTD;HWBudget;TotalMach;TotalOther;TotalOFMach
5710;GM K2XL Bracket FRT 5/D Belt
R;0;0;0;;0;0;;;0;;0;;0;0;0;0;0;0;0;0;0;20.5;0;0;0;0;0;18.5;40;0;0;0;0;0;0;0;0;0;457.56;328.8;;;;;
Sorry I don't know how to structure this nicer, I'll post an image of one of the rows in the excel file before and after I clear formatting as well.
Before:
http://imgur.com/f6jRBZR
After:
http://imgur.com/M1mQb8V
Is there a more efficient way to do this ?
Use fgetcsv() to read, clean and insert into your table. - http://www.php.net/fgetcsv
$row = 1;
if (($handle = fopen("test.csv", "r")) !== FALSE) {
while (($data = fgetcsv($handle, 10000, ";")) !== FALSE) {
$num = count($data);
echo "<p> $num fields in line $row: <br /></p>\n";
$row++;
for ($c=0; $c < $num; $c++) {
echo $data[$c] . "<br />\n";
}
}
fclose($handle);
}
INSERT INTO `job_budget_report`
( `Job_Num`
, `Description`
, `EngWeekly`
, `EngTTD`
, `EngBudget`
, `DesignWeekly`
, `DesignTTD`
, `DesignBudget`
, `DetailsWeekly`
, `DetailsTTD`
, `DetailsBudget`
, `EjectionWeekly`
, `EjectionTTD`
, `EjectionBudget`
, `CarbonEDMWeekly`
, `CarbonEDMTTD`
, `CarbonEDMBudget`
, `GdrillBMWeekly`
, `GdrillBMTTD`
, `GdrillBMBudget`
, `CNCWeekly`
, `CNCTTD`
, `CNCBudget`
, `MMQCOtherWeekly`
, `MMQCOtherTTD`
, `MMQCOtherBudget`
, `SpottingWeekly`
, `SpottingTTD`
, `SpottingBudget`
, `SpotPLWeekly`
, `SpotPLTTD`
, `SpotPLBudget`
, `HWWeekly`
, `HWTTD`
, `HWBudget`
, `TotalMach`
, `TotalOther`
, `TotalOFMach`
, `` -- clearly, this is the offending line!
) VALUES
('1000'
, 'description text here'
, '0'
, '0'
, '0'
, NULL
, '0'
, '0'
, NULL
, NULL
, '0'
, NULL
, '0'
, NULL
, '0'
, '0'
, '0'
, '0'
, '0'
, '0'
, '0'
, '0'
, '0'
, '20.5'
, '0'
, '0'
, '0'
, '0'
, '0'
, '18.5'
, '40'
, '0'
, '0'
, '0'
, '0'
, '0'
, '0'
, '0'
, ''); -- and its corresponding value
I have a table with the following structure:
CREATE TABLE IF NOT EXISTS `user_settings` (
`user_ID` smallint(6) unsigned NOT NULL,
`item` varchar(50) NOT NULL,
`value` text,
`app_ID` tinyint(4) NOT NULL DEFAULT '0',
KEY `user_ID` (`user_ID`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
# With these data
INSERT INTO `user_settings` (`user_ID`, `item`, `value`, `app_ID`) VALUES
(3, 'statusTrainer_ID', '0', 0),
(3, 'enabledApp', '1', 0),
(3, 'enabled_office_ID', '1', 1),
(3, 'enabled_office_ID', '2', 1),
(4, 'statusTrainer_ID', '1', 0),
(1, 'enabledApp', '1', 0),
(1, 'salesCode_ID_add', '1', 1),
(1, 'salesCode_ID_add', '2', 1),
(1, 'salesCode_ID_add', '3', 1),
(1, 'salesCode_ID_add', '20', 1),
(1, 'salesCode_ID_process', '2', 1),
(1, 'salesCode_ID_process', '3', 1),
(1, 'salesCode_ID_process', '20', 1);
I would like to run this query for data filtering
SELECT `user_ID`
FROM (`user_settings`)
WHERE (
`item` = 'enabledApp'
AND
`value` IN ('1')
)
AND
(
`item` = 'statusTrainer_ID'
AND
`value` IN ('0')
)
I am expecting '3' as result but MYSQL returns an empty set. why?? thanks for answer.
UPDATED
I solved it by subquery
SELECT distinct `user_ID`
FROM (`user_settings`)
WHERE user_ID IN(
SELECT `user_ID`
FROM (`user_settings`)
WHERE (
item = 'enabledApp'
AND
value IN (1)
))
AND user_ID IN(SELECT `user_ID`
FROM (`user_settings`)
WHERE (
item = 'statusTrainer_ID'
AND
value IN (0)
))
Demo
but it's little complicated...is there some cleaner solution????
You need an or:
SELECT `user_ID`
FROM (`user_settings`)
WHERE ( `item` = 'enabledApp' AND `value` IN ('1') ) OR
( `item` = 'statusTrainer_ID' AND `value` IN ('0') )
It returned the empty set because item cannot be both "enabledApp" and "statusTrainer_ID".
Oh, you are trying to get user ids that have both. Do it this way:
SELECT `user_ID`
FROM `user_settings`
GROUP BY `user_ID`
HAVING max(case when `item` = 'enabledApp' AND `value` IN ('1') then 1 else 0 end) = 1 and
max(case when `item` = 'statusTrainer_ID' AND `value` IN ('0') then 1 else 0 end) = 1
Demo
Problem:
Query aborts after 10 minutes
Query should be faster
I created the following query. This one was the fastest of several versions. Unfortunately, with more data, even this one abots after 600 seconds with an error "Error Code: 2013. Lost connection to MySQL server during query".
CREATE OR REPLACE VIEW 1 AS
SELECT `Timeperiod` AS `Timeperiod` ,
"at" AS `Domain` ,
`Content Groups`AS `Content Groups`,
...
FROM a
UNION ALL
SELECT `Timeperiod` AS `Timeperiod` ,
"com" AS `Domain` ,
`Content Groups`AS `Content Groups`,
...
FROM b
UNION ALL
SELECT `Timeperiod` AS `Timeperiod` ,
"com" AS `Domain`,
`Content Groups`AS `Content Groups`,
...
FROM c
UNION ALL
SELECT `Timeperiod` AS `Timeperiod` ,
"fr" AS `Domain`,
`Content Groups`AS `Content Groups`,
...
FROM d
UNION ALL
SELECT `Timeperiod` AS `Timeperiod` ,
"it" AS `Domain`,
`Content Groups`AS `Content Groups`,
...
FROM e;
CREATE OR REPLACE VIEW 2 AS
SELECT `Timeperiod` AS `Timeperiod` ,
`Content Group` AS `Content Group` ,
"at" AS `Domain`,
...
FROM f
UNION ALL
SELECT `Timeperiod` AS `Timeperiod` ,
`Content Group` AS `Content Group` ,
"com" AS `Domain`,
...
FROM g
UNION ALL
SELECT `Timeperiod` AS `Timeperiod` ,
`Content Group` AS `Content Group` ,
"com" AS `Domain`,
...
FROM h
UNION ALL
SELECT `Timeperiod` AS `Timeperiod` ,
`Content Group` AS `Content Group` ,
"fr" AS `Domain`,
...
FROM i
UNION ALL
SELECT `Timeperiod` AS `Timeperiod` ,
`Content Group` AS `Content Group` ,
"it" AS `Domain`,
...
FROM j;
CREATE OR REPLACE VIEW 3 AS
SELECT CG.`Domain` AS `Domain` ,
TP.`TimeperiodAlias` AS `Timeperiod` ,
CG.`Content Groups` AS `Content Group` ,
M.`InternalName` AS `Internal Model Name`,
...
FROM 1 CG ,
Timperiods TP ,
Models M
WHERE CG.`Content Groups` LIKE CONCAT(M.`ContentGroupName`, '%')
AND CG.`Timeperiod` = TP.`Timeperiod`;
CREATE OR REPLACE VIEW 4 AS
SELECT CGD.`Domain` AS `Domain` ,
TP.`TimeperiodAlias` AS `Timeperiod` ,
CGD.`Content Group` AS `Content Group`,
...
FROM 2 CGD,
Timeperiods TP ,
Models M
WHERE CGD.`Content Group` LIKE CONCAT(M.`ContentGroupName`, '%')
AND CGD.`Timeperiod` = TP.`Timeperiod`;
DROP TABLE IF EXISTS 5;
CREATE TABLE IF NOT EXISTS 5
(
`Domain` VARCHAR(3) NOT NULL ,
`Timeperiod` VARCHAR(30) NOT NULL,
`Content Group` varchar(70),
`Internal Model Name` VARCHAR(50),
...
PRIMARY KEY (`Domain`,`Timeperiod`, `Content Group`)
)
AS
SELECT CG.`Domain` AS `Domain` ,
CG.`Timeperiod` AS `Timeperiod` ,
CG.`Content Group` AS `Content Group` ,
CG.`Internal Model Name` AS `Internal Model Name`,
...
FROM 3 CG,
4 CGD
WHERE CG.`Content Group` = CGD.`Content Group`
AND CG.`Timeperiod` = CGD.`Timeperiod`
AND CG.`Domain` = CGD.`Domain`;
These are the number of rows of the steps:
1: 64763
2: 51932
Timeperiods: 36
Models: 15
3: 2706
4: 2172
This is the EXPLAIN:
'1', 'PRIMARY', 'M', 'ALL', NULL, NULL, NULL, NULL, '15', ''
'1', 'PRIMARY', 'M', 'index', NULL, 'CGIndex', '242', NULL, '15', 'Using index; Using join buffer'
'1', 'PRIMARY', '<derived3>', 'ALL', NULL, NULL, NULL, NULL, '9528', 'Using where; Using join buffer'
'1', 'PRIMARY', 'TP', 'eq_ref', 'PRIMARY', 'PRIMARY', '65', 'CG.Timeperiod', '1', ''
'1', 'PRIMARY', '<derived9>', 'ALL', NULL, NULL, NULL, NULL, '21226', 'Using where; Using join buffer'
'1', 'PRIMARY', 'TP', 'eq_ref', 'PRIMARY', 'PRIMARY', '65', 'CGD.Timeperiod', '1', 'Using where'
'9', 'DERIVED', 'ContentGroupDuration_jMKL35_ALL', 'ALL', NULL, NULL, NULL, NULL, '17794', ''
'10', 'UNION', 'ContentGroupDurationVisitDuration_k4cZ5M_ALL', 'ALL', NULL, NULL, NULL, NULL, '1', ''
'11', 'UNION', 'ContentGroupDurationVisitDuration_k4cZ5M_ALL', 'ALL', NULL, NULL, NULL, NULL, '1', ''
'12', 'UNION', 'ContentGroupDuration_jMKL35_ALL', 'ALL', NULL, NULL, NULL, NULL, '1', ''
'13', 'UNION', 'ContentGroupDuration_jMKL35_ALL', 'ALL', NULL, NULL, NULL, NULL, '1', ''
NULL, 'UNION RESULT', '<union9,10,11,12,13>', 'ALL', NULL, NULL, NULL, NULL, NULL, ''
'3', 'DERIVED', 'ContentGroups_fd33ef1_ALL', 'ALL', NULL, NULL, NULL, NULL, '1', ''
'4', 'UNION', 'ContentGroups_fd33ef1_ALL', 'ALL', NULL, NULL, NULL, NULL, '1', ''
'5', 'UNION', 'ContentGroups_fd33ef1_ALL', 'ALL', NULL, NULL, NULL, NULL, '1', ''
'6', 'UNION', 'ContentGroups_fd33ef1_ALL', 'ALL', NULL, NULL, NULL, NULL, '10476', ''
'7', 'UNION', 'ContentGroups_fd33ef1_ALL', 'ALL', NULL, NULL, NULL, NULL, '1', ''
NULL, 'UNION RESULT', '<union3,4,5,6,7>', 'ALL', NULL, NULL, NULL, NULL, NULL, ''
Does anyone know a way how to fasten the query and/or how to avoid the connection abort?
Solution:
Problem 1: execute "set wait_timeout=2147483" from command line (not inside sql)
Problem 2: store intermediate results in temporary tables and add indexes. Then perform the large join.
Best
Christian
I'd say there's two ways :
- either change the timeout on non interactive connections (wait_timeout for Mysql)
- or optimize somehow your table structure
I've been working on large commercial databases in the past, the performance of you joins relates more to the way your tables are indexes than to the amount of lines fetched. Make sure the right tables have the right keys, try to augment those if possible.
Anyway, change the wait_timeout, a connection shouldnt die so soon if you allow for long and complex queries.
To change the timeout, log in as root to mysql :
mysql -u root -p, input password, and enter the following :
set global wait_timeout=2147483
thats the max value corresponding to 23 days on windows. It can get much higher on Linux distribs, but well you don't need that long anyway.
cheers,