I need to count days (business days) between two dates excluding weekend (most important) and holidays
SELECT DATEDIFF(end_date, start_date) from accounts
But, I don't know how am I supposed to do it in MySQL, I found this article Count days between two dates, excluding weekends (MySQL only). I cannot figure out how to functional query in mysql, Can you give some information of how can achieve this with mysql query. If I am missing anything let me know.
[EDIT]
CREATE TABLE `candidatecase` (
`ID` int(11) NOT NULL AUTO_INCREMENT COMMENT 'Unique ID',
`CreatedBy` int(11) NOT NULL,
`UseraccountID` int(11) NOT NULL COMMENT 'User Account ID',
`ReportReadyID` int(11) DEFAULT NULL COMMENT 'Report Ready ID',
`DateCreated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'Date Created',
`InitiatedDate` timestamp NULL DEFAULT '0000-00-00 00:00:00' COMMENT 'Date Initiated',
`ActualCompletedDate` timestamp NULL DEFAULT '0000-00-00 00:00:00' COMMENT 'Date Completed Case',
`ProjectedCompletedDate` timestamp NULL DEFAULT '0000-00-00 00:00:00' COMMENT 'Date Projected Finish',
`CheckpackagesID` int(11) DEFAULT NULL COMMENT 'Default Check Package Auto Assign Once Initiate Start',
`Alacartepackage1` int(11) DEFAULT NULL COMMENT 'Ala carte Request #2',
`Alacartepackage2` int(11) DEFAULT NULL COMMENT 'Ala carte Request #3',
`OperatorID` int(11) NOT NULL COMMENT 'User Account - Operator',
`Status` int(11) NOT NULL COMMENT 'Status',
`caseRef` varchar(100) NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=293 ;
--
-- Dumping data for table `candidatecase`
--
INSERT INTO `candidatecase` (`ID`, `CreatedBy`, `UseraccountID`, `ReportReadyID`, `DateCreated`, `InitiatedDate`, `ActualCompletedDate`, `ProjectedCompletedDate`, `CheckpackagesID`, `Alacartepackage1`, `Alacartepackage2`, `OperatorID`, `Status`, `caseRef`) VALUES
(1, 43, 70, NULL, '2011-07-22 02:29:31', '2011-07-07 07:27:44', '2011-07-22 02:29:31', '2011-07-17 06:53:52', 11, NULL, NULL, 44, 6, ''),
(2, 43, 74, NULL, '2012-04-03 04:17:15', '2011-07-11 07:07:23', '2011-07-13 05:32:58', '2011-07-21 07:01:34', 20, 0, 0, 51, 0, ''),
(3, 43, 75, NULL, '2011-07-29 04:10:07', '2011-07-11 07:27:12', '2011-07-29 04:10:07', '2011-07-21 07:02:14', 20, NULL, NULL, 45, 6, ''),
(4, 43, 78, NULL, '2011-07-18 03:32:27', '2011-07-11 07:51:31', '2011-07-13 02:18:34', '2011-07-21 07:37:53', 20, NULL, NULL, 45, 6, ''),
(5, 43, 76, NULL, '2011-07-29 04:09:19', '2011-07-11 07:51:11', '2011-07-29 04:09:19', '2011-07-21 07:38:30', 20, NULL, NULL, 45, 6, ''),
(6, 43, 77, NULL, '2011-07-18 03:32:49', '2011-07-11 07:51:34', '2011-07-18 02:18:46', '2011-07-21 07:39:00', 20, NULL, NULL, 45, 6, ''),
(7, 43, 79, NULL, '2011-07-18 03:33:02', '2011-07-11 07:53:24', '2011-07-18 01:50:12', '2011-07-21 07:42:57', 20, NULL, NULL, 45, 6, ''),
(8, 43, 80, NULL, '2011-07-29 04:10:38', '2011-07-11 07:53:58', '2011-07-29 04:10:38', '2011-07-21 07:43:14', 20, NULL, NULL, 45, 6, ''),
(9, 43, 81, NULL, '2011-07-18 03:31:54', '2011-07-11 07:53:49', '2011-07-13 02:17:02', '2011-07-21 07:43:43', 20, NULL, NULL, 45, 6, ''),
(11, 43, 88, NULL, '2011-07-18 03:15:53', '2011-07-13 04:57:38', '2011-07-15 08:57:15', '2011-07-23 04:39:14', 12, NULL, NULL, 44, 6, ''),
(13, 43, 90, NULL, '2011-07-26 07:39:24', '2011-07-13 12:16:48', '2011-07-26 07:39:24', '2011-07-23 12:13:50', 15, NULL, NULL, 51, 6, ''),
(63, 43, 176, NULL, '2011-09-13 08:23:13', '2011-08-26 10:00:32', '2011-09-13 08:23:13', '2011-09-05 09:58:47', 41, NULL, NULL, 45, 6, ''),
(62, 43, 174, NULL, '2011-08-24 03:54:30', '2011-08-24 03:53:13', '2011-08-24 03:54:30', '2011-08-29 03:52:48', 17, NULL, NULL, 51, 6, ''),
(61, 43, 173, NULL, '2011-08-24 03:55:05', '2011-08-24 03:53:39', '2011-08-24 03:55:05', '2011-08-29 03:52:36', 17, NULL, NULL, 51, 6, ''),
(60, 43, 172, NULL, '2011-08-24 03:22:41', '2011-08-24 03:21:50', '2011-08-24 03:22:41', '2011-08-29 03:21:11', 17, NULL, NULL, 51, 6, ''),
(59, 43, 171, NULL, '2011-08-24 03:23:19', '2011-08-24 03:22:00', '2011-08-24 03:23:19', '2011-08-29 03:20:57', 17, NULL, NULL, 51, 6, '');
You might want to try this:
Count the number of working days (took it from here)
SELECT 5 * (DATEDIFF('2012-12-31', '2012-01-01') DIV 7) + MID('0123444401233334012222340111123400012345001234550', 7 * WEEKDAY('2012-01-01') + WEEKDAY('2012-12-31') + 1, 1)
This gives you 261 working days for 2012.
Now you need to know your holidays that are not on a weekend
SELECT COUNT(*) FROM holidays WHERE DAYOFWEEK(holiday) < 6
The result of this depends on your holiday table.
We need to get that in one query:
SELECT 5 * (DATEDIFF('2012-12-31', '2012-01-01') DIV 7) + MID('0123444401233334012222340111123400012345001234550', 7 * WEEKDAY('2012-01-01') + WEEKDAY('2012-12-31') + 1, 1) - (SELECT COUNT(*) FROM holidays WHERE DAYOFWEEK(holiday) < 6)
This should be it.
Edit: Please be aware that this only works properly if your end date is higher than your start date.
Create a table that contains all the weekends and holidays for the next 100whatever years.
You need to be able to specify when a day is a 'holiday' given that no one knows what the holidays will be for 2052 yet, you will not be able to make an accurate function at this time anyway. just update your non-work day table each year when the holidays become known (but you will always know the weekends).
Then your query becomes:
SELECT DATEFIFF(end_date, start_date) - COALESCE((SELECT COUNT(1) FROM nonWorkDays WHERE nonWorkDays.date BETWEEN start_date AND end_date), 0)
FROM accounts
If you really need to write a DATEDIFFWITHOUTWEEKENDSORHOLIDAYS function then just use the above and create a function (there's plenty of resources on how to make functions in each RDBMS).. just be sure to give it a better name. ^_^
One thing you will need to fix is I think there's a +1 missing somewhere in the above, for example DATEDIFF(today, today) if today is a weekend will return -1 instead of returning 0.
Something like this may work. Add all holiday dates and weekend dates to a table.
SELECT
DATEDIFF(end_date, start_date)
FROM table
WHERE date NOT IN (SELECT date FROM holidaydatestable )
Try This Code this will Calculate no of days Excluding Weekends
SELECT
(DATEDIFF(dd, #StartDate, #EndDate)+1)
-(DATEDIFF(wk, #StartDate, #EndDate) * 2)
from test_tbl where date NOT IN (SELECT date FROM holidaydatestable )
Make a function that will make a while cycle between the dates incrementing the number of days when it's not a saturday or sunday.
Related
I'm writing a query to update some chained rowsthat looks like this
SELECT T.Id,
T.Id + 1 AS NewID,
T.DifferenceTime,
RAT.AllowedDate,
RAT.ExpirationDate,
DATE_SUB(RAT.AllowedDate, INTERVAL T.DifferenceTime MINUTE) AS NewAllowedDate,
DATE_SUB(RAT.ExpirationDate, INTERVAL T.DifferenceTime MINUTE) AS NewExpiringDate
FROM ROOMS_ACCESS_TOKENS RAT
INNER JOIN (
SELECT T2.*,
ABS(TIMESTAMPDIFF(MINUTE,T2.ExpirationDate,UTC_TIMESTAMP())) AS DifferenceTime
FROM ROOMS_ACCESS_TOKENS RAT
INNER JOIN (
SELECT *
FROM ROOMS_ACCESS_TOKENS
WHERE Expired = 0 AND ExpirationDate > UTC_TIMESTAMP()
) AS T2 ON T2.IdRoom = RAT.IdRoom AND T2.ChainId = RAT.ChainId
WHERE RAT.IdRoom = 1
AND RAT.AccessToken = '5092FFA0B3721AE5EC757649DE983F8020220104215810'
AND RAT.RefId = 'B49F723F2FE0FD38063DA26F3EAEDBED'
AND RAT.KeyCode = '2773217uysagkasd8wqejhjkasdsm'
AND RAT.ExpirationDate > UTC_TIMESTAMP()
AND RAT.Expired = 0
) AS T ON T.IdRoom = RAT.IdRoom
AND T.ChainId = RAT.ChainId
AND T.AccessToken = RAT.AccessToken
AND T.RefId = RAT.RefId
AND T.AllowedDate = RAT.AllowedDate
This suppose to select a row by IdRoom, AccessToken, RefId, KeyCode and be above a certain date and not Expired.
Then get all chainded rows by ChainId and calculate time different between UTC_TIMESTAMP() and row ExpirationDate. (I guess it works till this point)
With that difference in minute, I want to calculate new datetimes but it doesn't work.
I've attached a screenshot with results
As you can see, it looks like NewAllowedDate and NewExpiringDate get calculated only for the first row.. But NewID gets calculated for all of them..
I can't understand where my query is wrong.
Any ideas?
Here the table and some data insert example
CREATE TABLE `ROOMS_ACCESS_TOKENS` ( `Id` int(11) NOT NULL, `IdRoom` int(11) DEFAULT NULL, `AccessToken` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL, `RefId` varchar(35) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL, `KeyCode` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, `Allowed` int(1) NOT NULL, `Used` int(1) NOT NULL, `Expired` int(1) NOT NULL DEFAULT '0', `ChainId` int(11) NOT NULL DEFAULT '1', `StartDate` datetime DEFAULT NULL, `AllowedDate` datetime NOT NULL, `ExpirationDate` datetime DEFAULT NULL, `ResidenceTime` int(5) NOT NULL, `Url` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `ROOMS_ACCESS_TOKENS` (`Id`, `IdRoom`, `AccessToken`, `RefId`, `KeyCode`, `Allowed`, `Used`, `Expired`, `ChainId`, `StartDate`, `AllowedDate`, `ExpirationDate`, `ResidenceTime`, `Url`) VALUES (1, 1, '5092FFA0B3721AE5EC757649DE983F8020220104215810', 'B49F723F2FE0FD38063DA26F3EAEDBED', '2773217uysagkasd8wqejhjkasdsm', 1, 1, 0, 1, '2022-01-04 22:30:46', '2022-01-04 22:30:46', '2022-01-04 23:30:46', 60, '/it'), (2, 1, '9CAB5CABB559260D41366E1041B46D0320220104233046', 'B086A4B3F4996C69B4DBB206C2E0D799', '2773217uysagkasd8wqejhjkasdsm', 0, 1, 0, 1, '2022-01-04 22:30:46', '2022-01-04 23:31:46', '2022-01-05 00:31:46', 60, '/it'), (3, 1, '3A2AE9CAC195B9938D25AE654790FAE020220104233046', 'E756AF83048259114F7E0BA04FFA799E', '2773217uysagkasd8wqejhjkasdsm', 0, 1, 0, 1, '2022-01-04 22:30:46', '2022-01-05 00:32:46', '2022-01-05 01:32:46', 60, '/it'), (4, 1, '17267FAC80875252F5F1E2585D078B1D20220104233046', '62143086CF25D276FD4C6D4465BDD41E', '2773217uysagkasd8wqejhjkasdsm', 0, 1, 0, 1, '2022-01-04 22:30:46', '2022-01-05 01:33:46', '2022-01-05 02:33:46', 60, '/it'), (5, 1, '39F47036B85694A231668BB8DFBF3CD120220104233046', 'C2C8F545B9FF7C59D50958C14EE61BF7', '2773217uysagkasd8wqejhjkasdsm', 0, 1, 0, 1, '2022-01-04 22:30:46', '2022-01-05 02:34:46', '2022-01-05 03:34:46', 60, '/it'), (6, 1, '61919A70C0D7AD4FB642BE1A3D6FE10420220104233046', 'EB1F2AF642C779B29F89023260A3AC94', '2773217uysagkasd8wqejhjkasdsm', 0, 1, 0, 1, '2022-01-04 22:30:46', '2022-01-05 03:35:46', '2022-01-05 04:35:46', 60, '/it'), (7, 1, '62BCFCCAC7F2EAFD5B1E06B32A810C1420220104233046', 'DDFB911F2197B50861AABD77005D9946', '2773217uysagkasd8wqejhjkasdsm', 0, 1, 0, 1, '2022-01-04 22:30:46', '2022-01-05 04:36:46', '2022-01-05 05:36:46', 60, '/it'), (8, 1, '6F72CCB6F3DF8F90C1A2911A7F1E097720220104233046', 'CCD116F4D4EFA9AE7D9B8DA780C5A73E', '2773217uysagkasd8wqejhjkasdsm', 0, 1, 0, 1, '2022-01-04 22:30:46', '2022-01-05 05:37:46', '2022-01-05 06:37:46', 60, '/it'), (9, 1, 'E8610F5C7551DA2695360B77431BBB1020220104233046', '49ABCCBDF6FC02FF290357B6A29DB2FC', '2773217uysagkasd8wqejhjkasdsm', 0, 1, 0, 1, '2022-01-04 22:30:46', '2022-01-05 06:38:46', '2022-01-05 07:38:46', 60, '/it'), (10, 1, '78BFEAF3EC52298B9EB5CDA8920168FE20220104233046', '755E481F29003C1EDC3A682D5037EF9F', '2773217uysagkasd8wqejhjkasdsm', 0, 0, 0, 1, '2022-01-04 22:30:46', '2022-01-05 07:39:46', '2022-01-05 08:39:46', 60, '/it');
ALTER TABLE `ROOMS_ACCESS_TOKENS` ADD PRIMARY KEY (`Id`), ADD KEY `IX_ACCESS_TOKEN` (`AccessToken`), ADD KEY `KeyCode` (`KeyCode`), ADD KEY `RefId` (`RefId`), ADD KEY `IdRoom` (`IdRoom`), ADD KEY `Allowed` (`Allowed`), ADD KEY `Used` (`Used`), ADD KEY `Expired` (`Expired`);
ALTER TABLE `ROOMS_ACCESS_TOKENS` MODIFY `Id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=11;
These sound redundant. The former one is dynamic; the latter one is potentially not-yet-set.
AND RAT.ExpirationDate > UTC_TIMESTAMP()
AND RAT.Expired = 0
I do not understand your date arithmetic, especially since the columns, being DATETIME, have 'second' resolution, yet the arithmetic involved 'MINUTEs'.
What is the meaning of "ABS" in ABS(TIMESTAMPDIFF(MINUTE,T2.ExpirationDate, UTC_TIMESTAMP())) AS DifferenceTime
Please do not use the same alias twice; it confuses me, and maybe the parser. (I am thinking of RAT, at least.)
I have to write a command that uses the following database:
CREATE TABLE `autori` (
`idAutor` mediumint(8) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
`numeAutor` varchar(255) NOT NULL
);
INSERT INTO `autori` (`idAutor`, `numeAutor`) VALUES
(1, 'Ion Creanga'),
(2, 'Walter Scott'),
(3, 'Mihai Eminescu'),
(4, 'George Bacovia'),
(5, 'William Shakespeare'),
(6, 'Agatha Christie'),
(7, 'Jules Verne');
CREATE TABLE `edituri` (
`idEditura` smallint(5) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
`numeEditura` varchar(255) NOT NULL
);
INSERT INTO `edituri` (`idEditura`, `numeEditura`) VALUES
(1, 'Litera'),
(2, 'CARTEA ROMANEASCA'),
(3, 'MONDORO'),
(4, 'RAO'),
(5, 'PENGUIN BOOKS'),
(6, 'Paralela 45'),
(7, 'CASA EDITORIALA DEMIURG PLUS');
CREATE TABLE `carti` (
`idCarte` int(10) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
`titluCarte` varchar(255) NOT NULL,
`idAutor` mediumint(8) UNSIGNED NOT NULL,
`nrPagini` smallint(5) UNSIGNED DEFAULT NULL,
`ISBN` varchar(17) NOT NULL,
`anPublicare` year(4) DEFAULT NULL,
`idEditura` smallint(5) UNSIGNED NOT NULL,
`stoc` smallint(5) UNSIGNED NOT NULL DEFAULT '0',
`refExterna` varchar(255) DEFAULT NULL,
UNIQUE KEY `isbnUnic` (`ISBN`),
FOREIGN KEY (`idAutor`) REFERENCES `autori` (`idAutor`) ON DELETE CASCADE ON UPDATE CASCADE,
FOREIGN KEY (`idEditura`) REFERENCES `edituri` (`idEditura`) ON DELETE CASCADE ON UPDATE CASCADE
);
INSERT INTO `carti` (`idCarte`, `titluCarte`, `idAutor`, `nrPagini`, `ISBN`, `anPublicare`, `idEditura`, `stoc`, `refExterna`) VALUES
(1, 'Amintiri din copilarie', 1, 48, '978-9975-74-380-8', 2014, 1, 5, NULL),
(2, 'Steaua Sudului', 7, 239, '978-973-23-3185-9', 2017, 2, 2, NULL),
(3, 'Sarpele de mare', 7, 199, '978-973-23-3184-2', 2017, 2, 1, NULL),
(4, '20.000 de leghe sub mari', 7, 300, '978-606-695-008-4', 2014, 3, 9, NULL),
(5, 'Crima din Orient Express', 6, 247, '978-606-609-620-1', 2017, 4, 20, NULL),
(6, 'Poirot investigheaza', 6, 217, '978-606-609-277-7', 2012, 4, 1, NULL),
(7, 'Journey to the Centre of the Earth', 7, 254, '978-0-14-062425-0', 1994, 5, 15, NULL),
(8, 'Cele mai frumoase povesti si povestiri', 1, 211, '978-973-47-2074-3', 2015, 6, 64, NULL),
(9, 'Poezii', 3, 382, '978-606-8395-85-2', 2014, 3, 32, NULL),
(10, 'Hamlet', 5, 228, '978-973-152-006-3', 2007, 7, 13, NULL);
CREATE TABLE `tipuriUtilizatori` (
`idTipUtilizator` tinyint(3) UNSIGNED NOT NULL,
`numeTip` varchar(255) NOT NULL
);
INSERT INTO `tipuriUtilizatori` (`idTipUtilizator`, `numeTip`) VALUES
(1, 'Necunoscut'),
(2, 'Bibliotecar'),
(3, 'Student');
CREATE TABLE `utilizatori` (
`idUtilizator` int(10) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`numeUtilizator` varchar(255) NOT NULL,
`idTipUtilizator` tinyint(3) UNSIGNED NOT NULL
);
INSERT INTO `utilizatori` (`idUtilizator`, `numeUtilizator`, `idTipUtilizator`) VALUES
(1, 'Xulescu', 3),
(2, 'Ygrec', 3),
(3, 'Zet', 0),
(4, 'Q', 2);
CREATE TABLE `imprumuturi` (
`idUtilizator` int(10) UNSIGNED NOT NULL,
`idCarte` int(10) UNSIGNED NOT NULL,
UNIQUE (`idUtilizator`,`idCarte`),
FOREIGN KEY (`idUtilizator`) REFERENCES `utilizatori` (`idUtilizator`) ON DELETE CASCADE ON UPDATE CASCADE,
FOREIGN KEY (`idCarte`) REFERENCES `carti` (`idCarte`) ON DELETE CASCADE ON UPDATE CASCADE
) ;
INSERT INTO `imprumuturi` (`idUtilizator`, `idCarte`) VALUES
(2, 3),
(3, 4),
(1, 5);
My command needs to return titluCarte, numeAutor, numeEditura, and also to subtract the rows of imprumuturi table from carti.stoc. I have managed to write this, but the subtracting doesn't return 162-3. What am I doing wrong?
SELECT titlucarte,
numeautor,
numeeditura,
stoc
FROM carti
JOIN autori
ON ( carti.idautor = autori.idautor )
JOIN edituri
ON ( carti.ideditura = edituri.ideditura )
UNION
SELECT '--------------------------------------',
'--------',
'--------',
'----'
UNION
SELECT 'total carti',
'--------',
'--------',
Sum(stoc)
FROM carti
UNION
SELECT '--------------------------------------',
'--------',
'--------',
'----'
UNION
SELECT 'carti disponibile',
'--------',
'--------',
Sum(carti.stoc) - (SELECT Count(*)
FROM imprumuturi)
FROM imprumuturi,
carti;
Every other things works well, my problem is with the subtraction from the end of the command.
If you want 159 change your last select query to below.
SELECT 'carti disponibile',
'--------',
'--------',
Sum(carti.stoc) - (SELECT Count(*) FROM imprumuturi)
FROM carti;
DEMO
The reason you get garbage value in the stoc column is because of the 14th line in your above code. Its expecting a number but you are changing the datatype to string and hence the garbage values.
Try changing ----- to a number like 0 for example and you should get the desired output
See below on sql fiddle
http://sqlfiddle.com/#!9/25e5a1/17
SELECT titlucarte,
numeautor,
numeeditura,
stoc
FROM carti
JOIN autori
ON ( carti.idautor = autori.idautor )
JOIN edituri
ON ( carti.ideditura = edituri.ideditura )
UNION
SELECT '--------------------------------------' as 'titlucarte',
'--------' as 'numeautor',
'--------' as 'numeeditura',
/*'----' as 'stoc' */ /*code removed*/
0 as stoc /* code added*/
UNION
SELECT 'total carti' as 'titlucarte',
'--------' as 'numeautor',
'--------' as 'numeeditura' ,
Sum(stoc) as 'stoc'
FROM carti
UNION
SELECT '--------------------------------------' as 'titlucarte',
'--------' as 'numeautor',
'--------' as 'numeeditura' ,
'----' as 'stoc'
UNION
SELECT 'carti disponibile' as 'titlucarte',
'--------' as 'numeautor',
'--------' as 'numeeditura' ,
Sum(carti.stoc) - (SELECT Count(*)
FROM imprumuturi) as 'stoc'
FROM /*imprumuturi,*/
carti;
I am working with the flights test data set.
CREATE TABLE IF NOT EXISTS `flights` (
`flightsKey` int(11) NOT NULL AUTO_INCREMENT,
`sno` varchar(10) DEFAULT NULL,
`year` int(4) DEFAULT NULL,
`month` int(2) DEFAULT NULL,
`day` varchar(10) DEFAULT NULL,
`dep_time` int(4) DEFAULT NULL,
`sched_dep_time` int(4) DEFAULT NULL,
`dep_delay` int(10) DEFAULT NULL,
`arr_time` int(4) DEFAULT NULL,
`sched_arr_time` int(4) DEFAULT NULL,
`arr_delay` int(10) DEFAULT NULL,
`carrier` varchar(2) DEFAULT NULL,
`flight` varchar(3) DEFAULT NULL,
`tailnum` varchar(10) NOT NULL,
`origin` varchar(3) DEFAULT NULL,
`dest` varchar(3) DEFAULT NULL,
`air_time` int(10) DEFAULT NULL,
`distance` int(10) DEFAULT NULL,
`hour` int(2) DEFAULT NULL,
`minute` int(3) DEFAULT NULL,
`fullDate` varchar(12) DEFAULT NULL,
PRIMARY KEY (`flightsKey`),
KEY `origin` (`origin`),
KEY `carrier` (`carrier`),
KEY `dest` (`dest`),
KEY `tailnum` (`tailnum`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=336868 ;
--
-- Dumping data for table `flights`
--
INSERT INTO `flights` (`flightsKey`, `sno`, `year`, `month`, `day`, `dep_time`, `sched_dep_time`, `dep_delay`, `arr_time`, `sched_arr_time`, `arr_delay`, `carrier`, `flight`, `tailnum`, `origin`, `dest`, `air_time`, `distance`, `hour`, `minute`, `fullDate`) VALUES
(1, '1', 2013, 1, '1', 517, 515, 2, 830, 819, 11, 'UA', '154', 'N14228', 'EWR', 'IAH', 227, 1400, 5, 15, '0000-00-00'),
(2, '2', 2013, 1, '1', 533, 529, 4, 850, 830, 20, 'UA', '171', 'N24211', 'LGA', 'IAH', 227, 1416, 5, 29, '0000-00-00'),
(3, '3', 2013, 1, '1', 542, 540, 2, 923, 850, 33, 'AA', '114', 'N619AA', 'JFK', 'MIA', 160, 1089, 5, 40, '0000-00-00'),
(4, '4', 2013, 1, '1', 544, 545, -1, 1004, 1022, -18, 'B6', '725', 'N804JB', 'JFK', 'BQN', 183, 1576, 5, 45, '0000-00-00'),
(5, '5', 2013, 1, '1', 554, 600, -6, 812, 837, -25, 'DL', '461', 'N668DN', 'LGA', 'ATL', 116, 762, 6, 0, '0000-00-00'),
(6, '6', 2013, 1, '1', 554, 558, -4, 740, 728, 12, 'UA', '169', 'N39463', 'EWR', 'ORD', 150, 719, 5, 58, '0000-00-00'),
(7, '7', 2013, 1, '1', 555, 600, -5, 913, 854, 19, 'B6', '507', 'N516JB', 'EWR', 'FLL', 158, 1065, 6, 0, '0000-00-00'),
(8, '8', 2013, 1, '1', 557, 600, -3, 709, 723, -14, 'EV', '570', 'N829AS', 'LGA', 'IAD', 53, 229, 6, 0, '0000-00-00'),
(9, '9', 2013, 1, '1', 557, 600, -3, 838, 846, -8, 'B6', '79', 'N593JB', 'JFK', 'MCO', 140, 944, 6, 0, '0000-00-00'),
(10, '10', 2013, 1, '1', 558, 600, -2, 753, 745, 8, 'AA', '301', 'N3ALAA', 'LGA', 'ORD', 138, 733, 6, 0, '0000-00-00');
I can get the query working by using views but I am trying to figure out what is causing my nested query to hang
This works without problem. Lets call it query 1:
SELECT carrier FROM flights GROUP BY carrier HAVING COUNT(*) <5000
it produces the following list:
('AS', 'F9','FL', 'HA', 'OO', 'YV')
This also works without problem. lets call it query 2.
SELECT origin, AVG(dep_delay) FROM flights
WHERE carrier IN ('AS', 'F9','FL', 'HA', 'OO', 'YV')
GROUP BY origin
However, when you use the query 1 as in inner query in query 2, it gets stuck:
SELECT origin, AVG(dep_delay) FROM flights
WHERE carrier IN (SELECT carrier FROM flights GROUP BY carrier HAVING COUNT(*) <5000)
GROUP BY origin
I also tried this and it worked without a hitch. I created a view for inner query:
CREATE view smallCarriers AS
SELECT carrier FROM flights GROUP BY carrier HAVING COUNT(*) <5000
Then I used the view as an inner query in the nested query:
SELECT origin, AVG(dep_delay) FROM flights
WHERE carrier IN (SELECT * FROM smallCarriers)
GROUP BY origin
Basically everything worked except for the explicit nested query.
I am running Mysql version 5.5.62 on Ubuntu 14.04. I am running these queries in phpmyadmin and the status of the query says "sending data" when it hangs.
I have included a link to the SQL fiddle here:
http://sqlfiddle.com/#!9/605236/5
It seems to work - so my question is why?
The actual table has 336776 rows. I tried both InnoDB and MyISAM thinking something was going on with the way the referential integrity was setup but I still have the same issue. What about this query causes the script to hang?
note - I have also tried the query from the mysql shell directly with the same result.
I have added the EXPLAIN result from the query which hangs:
mysql> EXPLAIN SELECT origin, AVG(dep_delay) FROM flights WHERE carrier IN (SELECT carrier FROM flights GROUP BY carrier HAVING COUNT(*) <5000) GROUP BY origin;
+----+--------------------+---------+-------+---------------+---------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+---------+-------+---------------+---------+---------+------+--------+-------------+
| 1 | PRIMARY | flights | index | NULL | origin | 12 | NULL | 337143 | Using where |
| 2 | DEPENDENT SUBQUERY | flights | index | NULL | carrier | 9 | NULL | 42183 | Using index |
+----+--------------------+---------+-------+---------------+---------+---------+------+--------+-------------+
2 rows in set (0.01 sec)
I have two tables, candidates and candidate_subjects, for storing candidate details and candidate scores respectively. I want a query to update candidate remark to 'FAIL' if the candidate pass less than 6 subjects. To pass a subject, the candidate sum of ca_score and exam_score for a subject must be greater than 40.
Below is the query I have written but it is not giving the result expected:
UPDATE candidates SET candidates.remark='FAIL' WHERE (select
count(candidate_subjects.id) AS total_pass from candidates,
candidate_subjects where candidates.id=candidate_subjects.candidate_id
and (candidate_subjects.ca_score + candidate_subjects.exam_score) >= 40) < 6
The tables:
CREATE TABLE candidate_subjects (
id INT(10) PRIMARY KEY NOT NULL AUTO_INCREMENT,
candidate_id INT(11),
exam_type_id INT(10),
subject_id INT(10),
ca_score INT(11),
exam_score INT(6),
score_grade VARCHAR(10),
date_created VARCHAR(10),
date_modified TIMESTAMP
);
INSERT INTO `candidate_subjects` (`id`, `candidate_id`, `exam_type_id`,
`subject_id`, `ca_score`, `exam_score`, `score_grade`, `date_created`,
`date_modified`) VALUES
(1, 2, 1, 32, 22, 61, NULL, '2017-02-01', '2017-08-28 13:10:33'),
(2, 2, 1, 5, 21, 38, NULL, '2017-02-01', '2017-08-28 13:10:33'),
(3, 2, 1, 14, 21, 51, NULL, '2017-02-01', '2017-08-28 13:10:33'),
(4, 2, 1, 1, 19, 34, NULL, '2017-02-01', '2017-08-28 13:10:33'),
(5, 2, 1, 2, 23, 39, NULL, '2017-02-01', '2017-08-28 13:10:33'),
(6, 2, 1, 38, 20, 32, NULL, '2017-02-01', '2017-08-28 13:10:33'),
(7, 2, 1, 53, 24, 47, NULL, '2017-02-01', '2017-08-28 13:10:33'),
(8, 4, 1, 32, 19, 61, NULL, '2017-02-01', '2017-08-28 13:11:27'),
(9, 4, 1, 5, 22, 41, NULL, '2017-02-01', '2017-08-28 13:11:27'),
(10, 4, 1, 14, 20, 46, NULL, '2017-02-01', '2017-08-28 13:11:27'),
(11, 4, 1, 1, 23, 37, NULL, '2017-02-01', '2017-08-28 13:11:27'),
(12, 4, 1, 2, 21, 36, NULL, '2017-02-01', '2017-08-28 13:11:27'),
(13, 4, 1, 38, 22, 34, NULL, '2017-02-01', '2017-08-28 13:11:27'),
(14, 4, 1, 53, 24, 52, NULL, '2017-02-01', '2017-08-28 13:11:27'),
(15, 5, 1, 32, 20, 62, NULL, '2017-02-01', '2017-08-28 13:11:44'),
(16, 5, 1, 5, 22, 38, NULL, '2017-02-01', '2017-08-28 13:11:44');
CREATE TABLE candidates (
id INT(11) PRIMARY KEY NOT NULL AUTO_INCREMENT,
exam_no VARCHAR(15),
surname VARCHAR(50),
other_names VARCHAR(100),
school_id INT(11),
registration_completed INT(11),
exam_scores_completed INT(5),
remark VARCHAR(10)
);
INSERT INTO candidates (id, exam_no, surname, other_names, school_id,
registration_completed, exam_scores_completed, remark) VALUES
(1, '1171052001', 'ABADO', 'MASENENGEN', 1052, 1, '1', ''),
(2, '1170938001', 'AGBA', 'NGUHER', 938, 1, '1', ''),
(3, '1170071001', 'ABEE', 'SESUUR', 71, 1, '1', ''),
(4, '1170938002', 'AHEN', 'REBECCA DOOSUUN', 938, 1, '1', '');
To update your candidates according to your criteria and their records exists in candidate_subjects you can use below query.
UPDATE candidates c
JOIN (select
count(id) AS total_pass ,candidate_id
from candidate_subjects
where(ca_score + exam_score) >= 40
group by candidate_id
) a on c.id = a.candidate_id
SET c.remark='FAIL'
WHERE total_pass < 6
DEMO
Can you try something like:
UPDATE candidates SET candidates.remark='FAIL' WHERE candidate_id IN (SELECT candidate_id FROM candidate_subject WHERE candidatescorecondition>40 HAVING COUNT(*) > 6);
Please run in a dev environment first!
If candidates can be marked as FAIL without doing all the exams you can do something like this:
update candidates set remark='FAIL'
where id in (
select candidate_id from candidate_subjects
where ca_score+exam_score > 40 -- passed subject
group by candidate_id having count(*)<6
)
but if a candidate must have data for at least six subjects in order to be evaluated you need to add an extra condition (so a candidate is not marked as failed if he/she is in the middle of the process):
update candidates set remark='FAIL'
where id in (
select candidate_id from candidate_subjects
where ca_score+exam_score > 40 -- passed subject
group by candidate_id having count(*)<6
)
and id in (
select candidate_id from candidate_subjects
group by candidate_id having count(*)>=6 -- the candidate has data for at leas 6 subjects
)
First table
CREATE TABLE IF NOT EXISTS `city_node` (
`node_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`title` varchar(50) NOT NULL,
`parent_node_id` int(10) unsigned NOT NULL DEFAULT '0',
`lft` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Nested set info ''left'' value',
`rgt` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Nested set info ''right'' value',
`depth` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Depth = 0: no parent',
PRIMARY KEY (`node_id`),
KEY `parent_node_id` (`parent_node_id`),
KEY `lft` (`lft`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=26;
And data
INSERT INTO `city_node` (`node_id`, `title`, `parent_node_id`, `lft`, `rgt`, `depth`) VALUES
(1, 'Great Britain', 0, 1, 20, 0),
(3, 'England', 1, 2, 9, 1),
(7, 'Scotland', 1, 16, 19, 1),
(8, 'Edinburgh', 7, 17, 18, 2),
(9, 'Wales', 1, 10, 15, 1),
(10, 'Cardiff', 9, 11, 12, 2),
(11, 'London', 3, 3, 4, 2),
(12, 'Birmingham', 3, 5, 6, 2),
(13, 'Germany', 0, 21, 26, 0),
(14, 'Stuttgart', 13, 22, 23, 1),
(15, 'Newport', 9, 13, 14, 2),
(16, 'Munich', 13, 24, 25, 1),
(17, 'Israel', 0, 27, 32, 0),
(18, 'Tel Aviv', 17, 28, 29, 1),
(19, 'Ashdod', 17, 30, 31, 1),
(20, 'USA', 0, 33, 38, 0),
(21, 'New York', 20, 34, 35, 1),
(24, 'Liverpool', 3, 7, 8, 2),
(25, 'Detroit', 20, 36, 37, 1);
Second table
CREATE TABLE IF NOT EXISTS `city_node_entity` (
`node_id` int(10) NOT NULL,
`entity` tinyint(3) unsigned NOT NULL DEFAULT '1',
KEY `node_id` (`node_id`,`entity`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
And data
INSERT INTO `city_node_entity` (`node_id`, `entity`) VALUES
(11, 1),
(12, 1),
(16, 1),
(19, 1);
I want to get node with entity 1 and its ancestors, like this
Great Britain
--England
----London
----Birmingham
Germany
--Munich
Israel
--Ashdod
So, my query is
SELECT DISTINCT(node_ext.node_id), node_ext.*
FROM city_node_entity AS entity
LEFT JOIN city_node AS node
ON entity.node_id = node.node_id
LEFT JOIN city_node AS node_ext
ON node_ext.lft <= node.lft AND node_ext.rgt >= node.rgt
WHERE entity.entity = 1
ORDER BY node_ext.lft
But explain shows
-Using where; Using index; Using temporary; Using filesort
Is there any other queries to get same result but with less [EXTRA]?
The only thing you can do for recursive queries is to run it with joins for each parent/child.... because your second table is the actual city name and you want to work backwards you can do it like this... just add more joins till all results are null and you will have yourself the full tree
SELECT node.title AS child, t2.title as parent1, t3.title as parent2, t4.title as parent3
FROM city_node_entity AS entity
LEFT JOIN city_node AS node ON entity.node_id = node.node_id
LEFT JOIN city_node AS t2 ON t2.node_id = node.parent_node_id
LEFT JOIN city_node AS t3 ON t3.node_id = t2.parent_node_id
LEFT JOIN city_node AS t4 ON t4.node_id = t3.parent_node_id;
Fiddle Demo