Reputation: 1149
I'm trying to create a crosstab but I need a kind of query that repeat each policy_business_unit group by cia_ensures
My tables:
|policies|
|id| |client| |policy_business_unit_id| |cia_ensure_id| |state|
1 MATT 1 1 0
2 STEVE 2 1 0
3 BILL 3 2 0
4 LARRY 4 2 1
|policy_business_units|
|id| |name| |comercial_area_id|
1 LIFE 1
2 ROB 1
3 SECURE 1
4 ACCIDENT 1
|comercial_areas|
|id| |name|
1 BANK
2 HOSPITAL
|cia_ensures|
|id| |name|
1 SPRINT
2 APPLE
Here is the information:
http://sqlfiddle.com/#!2/4750f/2
I'm trying to get states = 0,1,2 anc count if it doesn't exist or show 0
Select
pb.name as BUSINESS_UNITS,
ce.name as CIA,ca.name as COMERCIAL_AREAS,
if (p.state = 0, count(p.state), 0) as state_0,
if (p.state = 1, count(p.state), 0) as state_1,
if (p.state = 2, count(p.state), 0) as state_2
From policies p
INNER JOIN policy_business_units pb ON pb.id = p.policy_business_unit_id
INNER JOIN comercial_areas ca ON ca.id = pb.comercial_area_id
INNER JOIN cia_ensures ce ON ce.id = p.cia_ensure_id
where ca.id=1
group by pb.id
I'm getting this result:
BUSINESS_UNITS CIA COMERCIAL_AREAS STATE_0 STATE_1 STATUS_2
LIFE SPRINT BANK 1 0 0
ROB SPRINT BANK 1 0 0
SECURE APPLE BANK 1 0 0
ACCIDENT APPLE BANK 0 1 0
Here is my problem:
How can I do to have this result?
BUSINESS_UNITS CIA COMERCIAL_AREAS STATE_0 STATE_1 STATUS_2
LIFE SPRINT BANK 1 0 0
ROB SPRINT BANK 1 0 0
SECURE SPRINT BANK 0 0 0
ACCIDENT SPRINT BANK 0 0 0
LIFE APPLE BANK 0 0 0
ROB APPLE BANK 0 0 0
SECURE APPLE BANK 1 0 0
ACCIDENT APPLE BANK 0 1 0
I tried
SELECT
COALESCE(SUM(CASE WHEN p.state = 0 THEN 1 ELSE 0 END),0) AS state_0,
COALESCE(SUM(CASE WHEN p.state = 1 THEN 1 ELSE 0 END),0) AS state_1,
COALESCE(SUM(CASE WHEN p.state = 2 THEN 1 ELSE 0 END),0) AS state_2,
count(*) AS total, p.policy_business_unit_id as units,
p.cia_ensure_id AS cias, p.state as status
FROM policies p
WHERE policy_business_unit_id IN (1)
AND cia_ensure_id IN (1,2)
GROUP BY cia_ensure_id
Somebody knows how to do that?
Please I will appreciate all kind of help. Thanks.
Upvotes: 1
Views: 127
Reputation: 1515
You have to use subqueries and then apply a LEFT OUTER JOIN
to join them together. The IFNULL
part at the top ensures that the filled up NULL
values in the not existing state fields, resulting from the outer join, are converted to 0.
SET @id = 1;
SELECT sections.BUSINESS_UNITS, sections.CIA, sections.AREAS,
IFNULL(states.state_0, 0) AS STATE_0,
IFNULL(states.state_1, 0) AS STATE_1,
IFNULL(states.state_2, 0) AS STATE_2
FROM (
SELECT
pb.id AS bus_id, pb.name AS BUSINESS_UNITS,
ce.id AS cia_id, ce.name AS CIA,
ca.name AS AREAS
FROM policies p
INNER JOIN policy_business_units pb
ON pb.id = p.policy_business_unit_id
INNER JOIN comercial_areas ca
ON ca.id = pb.comercial_area_id
INNER JOIN cia_ensures ce
WHERE ca.id = @id
) AS sections
LEFT OUTER JOIN (
SELECT
pb.id AS bus_id,
ce.id AS cia_id,
if (p.state = 0, 1, 0) AS state_0,
if (p.state = 1, 1, 0) AS state_1,
if (p.state = 2, 1, 0) AS state_2
FROM policies p
INNER JOIN policy_business_units pb
ON pb.id = p.policy_business_unit_id
INNER JOIN comercial_areas ca
ON ca.id = pb.comercial_area_id
INNER JOIN cia_ensures ce
ON ce.id = p.cia_ensure_id
WHERE ca.id = @id
) AS states
ON sections.bus_id = states.bus_id
AND sections.cia_id = states.cia_id
ORDER BY sections.cia_id;
DEMO @ SQL Fiddle
Upvotes: 1