Reputation: 51
Hello I have the following two tables which represents a document with its stage and a history table that shows the time document was moved to next stage
CREATE TABLE `document` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`description` text,
`stage` tinyint(4) NOT NULL DEFAULT '0',
`customer_name` varchar(100) DEFAULT NULL,
`creator_id` bigint(20) NOT NULL DEFAULT '0',
`customer_city` varchar(100) DEFAULT NULL,
`customer_state` varchar(100) DEFAULT NULL,
`customer_zip` varchar(50) DEFAULT NULL,
`customer_contact` varchar(100) DEFAULT NULL,
`number` varchar(100) DEFAULT NULL,
`latitude` float NOT NULL DEFAULT '0',
`longitude` float NOT NULL DEFAULT '0',
`creation_date` varchar(50) DEFAULT NULL,
`expanded_description` text,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `document_history` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`doc_id` bigint(20) NOT NULL,
`modifying_time` datetime DEFAULT NULL,
`changed_to_stage` tinyint(3) unsigned DEFAULT NULL,
`old_stage` tinyint(3) unsigned DEFAULT NULL,
`user_modified` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
I need to get count statistics based on selected period.For example I need to know how many documents were in stage 1 during selected period, but the problem is that if a document was in several different stages during this period - I have to count it only for the last stage, e.g. if doc was in stage 1 and after that in stage 2 - I need to count it only for stage 2.
Here is what I have till now:
SELECT
round(sum(case when dh.modifying_time between '2016-09-15' and '2016-09-24' and dh.changed_to_stage = 1 then 1 else 0 end),0) entry_count,
round(sum(case when dh.modifying_time between '2016-09-15' and '2016-09-24' and dh.changed_to_stage = 3 then 1 else 0 end),0) pricing_count,
round(sum(case when dh.modifying_time between '2016-09-15' and '2016-09-24' and dh.changed_to_stage = 5 then 1 else 0 end),0) executed_count,
round(sum(case when dh.modifying_time between '2016-09-15' and '2016-09-24' and dh.changed_to_stage = 7 then 1 else 0 end),0) approved_count,
round(sum(case when dh.modifying_time between '2016-09-15' and '2016-09-24' and dh.changed_to_stage = 9 then 1 else 0 end),0) canceled_count
FROM document doc join document_history dh on doc.id=dh.doc_id
The problem here is that the document is counted twice if it was in two different stages in that period.
Any help will be appreciated.
Thanks and best regards
Upvotes: 0
Views: 35
Reputation: 1269773
You want to select just the last stage, then you can do the logic in the where
. But, I would suggest moving the date condition to the WHERE
first and getting rid of ROUND()
(for intengers? really?):
SELECT sum(case when dh.changed_to_stage = 1 then 1 else 0 end) as entry_count,
sum(case when dh.changed_to_stage = 3 then 1 else 0 end) as pricing_count,
sum(case when dh.changed_to_stage = 5 then 1 else 0 end) as executed_count,
sum(case when dh.changed_to_stage = 7 then 1 else 0 end) as approved_count,
sum(case when dh.changed_to_stage = 9 then 1 else 0 end) as canceled_count
FROM document doc join
document_history dh
on doc.id = dh.doc_id
WHERE dh.modifying_time between '2016-09-15' and '2016-09-24' and
dh.modifying_time = (SELECT MAX(dh2.modifying_time)
FROM document_history dh2
WHERE dh2.doc_id = dh.doc_id AND
dh2.modifying_time between '2016-09-15' and '2016-09-24'
);
Notes:
creation_date
).between
with dates or datetime. Your expression probably does not do what you intend. Write it as dh.modifying_time >= '2016-09-15' and dh.modifying_time < '2016-09-25'
, which is probably what you intend.left join
instead of an inner join
and move the where
conditions to an on
clause.round()
with an integer argument? I just don't get that one.document
table at all, only document_history
. You might consider from document_history
as a simplification.Upvotes: 1