Join between Tables in SQL - mysql

I have 5 tables
1. SCHOOL[id(bigInt, primary), name(varchar)]
2. SELECTED_INDICATOR[id(bigInt, primary), school_id(bigint)]
3. TEACHER[id(bigint, primary), indicator_id(bigInt), attendance_id(int)]
4. STUDENT[id(bigint, primary), indicator_id(bigInt), attendance_id(int)]
5. MIDDAY_MEAL[id(bigint,primary), indicator_id(bigint), served(boolean), consumed_number(int)]
in TEACHER table, attendance_id can have value: 1 or 2 or 3.
Similarly, in STUDENT table, attendance_id can have value: 1 or 2.
I have to generate a report based on the SELECTED_INDICATOR id, in a format as:
School_id | School_Name | Total_Teacher | Teacher_1 | Teacher_2 | Teacher_3 | Total_Student | Student_1 | Student_2 | served | consumed_number
for this I have tried as:
select A.id, A.school_id, SC.name,
SUM(CASE WHEN T.attendance_id IN (1,2,3) THEN 1 ELSE 0 END) as TOTAL_TEACHER,
SUM(CASE WHEN T.attendance_id IN (1) THEN 1 ELSE 0 END) as TEACHERS_1,
SUM(CASE WHEN T.attendance_id IN (2) THEN 1 ELSE 0 END) as TEACHERS_2,
SUM(CASE WHEN T.attendance_id IN (3) THEN 1 ELSE 0 END) as TEACHERS_3,
SUM(CASE WHEN S.attendance_id IN (1,2) THEN 1 ELSE 0 END) as TOTAL_STUDENT,
SUM(CASE WHEN S.attendance_id IN (1) THEN 1 ELSE 0 END) as STUDENTS_1,
SUM(CASE WHEN S.attendance_id IN (2) THEN 1 ELSE 0 END) as STUDENTS_2,
M.served, M.consumed_number
from SELECTED_INDICATOR A
join SCHOOL SC on A.school_id = SC.id
join TEACHER T on A.id = T.indicator_id
join STUDENT S on A.id = S.indicator_id
join MIDDAY_MEAL M on A.id = M.indicator_id
WHERE A.STATUS = 'COMPLETED' group by A.id;
When I join TEACHER or STUDENT with SELECTED_INDICATOR one at a time, it gives me the correct data. But when I join both the TEACHER and STUDENT with SELECTED_INDICATOR as in the above query, I get huge numbers for teacher and student related fields.
what is wrong with my query? Please help to correct it, or give any alternative query.

Try using COUNT() that have the options to use distincted values. The problem is that the tables are multiplying the results.
select A.id, A.school_id, SC.name,
COUNT(DISTINCT CASE WHEN T.attendance_id IN (1,2,3) THEN t.TeacherID END) as TOTAL_TEACHER,
COUNT(DISTINCT CASE WHEN T.attendance_id IN (1) THEN t.TeacherID END) as TEACHERS_1,
....
FROM ....

SELECT A.id, A.school_id, SC.name,
(SELECT COUNT(T.attendance_id) FROM TEACHER T GROUP BY T.indicator_id HAVING A.id = T.indicator_id) AS TOTAL_TEACHER,
(SELECT COUNT(T.attendance_id) FROM TEACHER T WHERE T.attendance_id = 1 GROUP BY T.indicator_id HAVING A.id = T.indicator_id) AS TEACHERS_1,
(SELECT COUNT(T.attendance_id) FROM TEACHER T WHERE T.attendance_id = 2 GROUP BY T.indicator_id HAVING A.id = T.indicator_id) AS TEACHERS_2,
(SELECT COUNT(T.attendance_id) FROM TEACHER T WHERE T.attendance_id = 3 GROUP BY T.indicator_id HAVING A.id = T.indicator_id) AS TEACHERS_3,
(SELECT COUNT(S.attendance_id) FROM STUDENT S GROUP BY S.indicator_id HAVING A.id = S.indicator_id) AS TOTAL_STUDENT,
(SELECT COUNT(S.attendance_id) FROM STUDENT S WHERE S.attendance_id = 1 GROUP BY S.indicator_id HAVING A.id = S.indicator_id) AS STUDENTS_1,
(SELECT COUNT(S.attendance_id) FROM STUDENT S WHERE S.attendance_id = 2 GROUP BY S.indicator_id HAVING A.id = S.indicator_id) AS STUDENTS_2,
M.served, M.consumed_number
FROM SELECTED_INDICATOR A
JOIN SCHOOL SC on A.school_id = SC.id
JOIN MIDDAY_MEAL M on A.id = M.indicator_id

Related

[HY000][1111] Invalid use of group function

I have searched a lot ,but none of other questions with error 1111 solves my problem.
My needs are to count the distinct phone number of some id
The following code works:
SELECT
a.id_borrow_application,
count(DISTINCT c.phone_no) CVG_CALL_OUT_COUNTS_6M
FROM t_snow_borrow_application_id a
JOIN t_snow_call_mobile b
JOIN t_snow_call_record_201612 c ON
(
a.id_borrow_application = b.id_borrow_application
AND b.id = c.id_call_mobile
)
WHERE c.call_type = 0
GROUP BY a.id_borrow_application;
But when I want to write 4 similar queries together,the error in title
happens.
[HY000][1111] Invalid use of group function
SELECT
a.id_borrow_application,
sum(CASE WHEN call_type = 0
THEN count(DISTINCT c.phone_no)
ELSE 0 END) CVG_CALL_OUT_COUNTS_6M,
sum(CASE WHEN call_type = 0 AND c.days <= 30
THEN count(DISTINCT c.phone_no)
ELSE 0 END) CVG_CALL_OUT_COUNTS_1M,
sum(CASE WHEN call_type = 1
THEN count(DISTINCT c.phone_no)
ELSE 0 END) CVG_CALL_IN_COUNTS_6M,
sum(CASE WHEN call_type = 1 AND c.days <= 30
THEN count(DISTINCT c.phone_no)
ELSE 0 END) CVG_CALL_IN_COUNTS_1M
FROM t_snow_borrow_application_id a
JOIN t_snow_call_mobile b
JOIN t_snow_call_record_201612 c ON
(
a.id_borrow_application = b.id_borrow_application
AND b.id = c.id_call_mobile
)
GROUP BY a.id_borrow_application;
Do I have to write 4 queries?
You are nesting aggregate function which is not allowed in MySQL.
You don't actually need the sum function for count distinct phone_nos for different conditions. Take the count (distinct outside the case and remove sum function and else clause of the case.
Try this:
select a.id_borrow_application,
count(distinct case when call_type = 0 then c.phone_no end) CVG_CALL_OUT_COUNTS_6M,
count(distinct case when call_type = 0
and c.days <= 30 then c.phone_no end) CVG_CALL_OUT_COUNTS_1M,
count(distinct case when call_type = 1 then c.phone_no end) CVG_CALL_IN_COUNTS_6M,
count(distinct case when call_type = 1
and c.days <= 30 then c.phone_no end) CVG_CALL_IN_COUNTS_1M
from t_snow_borrow_application_id a
join t_snow_call_mobile b
join t_snow_call_record_201612 c on (
a.id_borrow_application = b.id_borrow_application
and b.id = c.id_call_mobile
)
group by a.id_borrow_application;

SQL query time difference when adding an inner join and group by gives wrong calculations

Am trying to come up with an sql query to calculate, the time difference from a start time and an end time, then sum up the duration for each school.
I have the following table :
-Class /*Contains all the classes tied to a school using school_id */
-School /*contains all the schools in tied to a hub using hub_id */
-Hub /*contains all the hubs details (one hub can have many schools in it) */
-student /*contains student profile, which is tied to a class using class_id */
-session_details /contains the session details which include the session start time, end time, session_id,/
-student_attendance_register /* used to mark the register for all the students in a class for a particular session using session_id
and student_id as in_attendance=0 or in_attendance =1 /*
I have a mini query which works perfect, the query calculates the duration of the session and finds the total duration for all the classes in a school.
select
c.class_name,c.school_id,d.school_name,e.session_date,e.time_finish,e.time_start,
CAST(sum(TIMEDIFF(e.time_finish, e.time_start)) as TIME) as duration
From session_details as e
Inner join class as c
on c.id = e.class_id
Inner join school as d
on c.school_id = d.id
group by c.school_id;
My problem pops up when i add inner joins to get the student profile and their attendance. See below my query
select
a.session_details_id,c.class_name,c.school_id,d.school_name,
e.class_id,e.session_date,e.time_finish,e.time_start,
SUM((TIME_TO_SEC(e.time_finish) - TIME_TO_SEC(e.time_start))/60) as session_duration,
COUNT(CASE WHEN a.in_attendance = 1 and b.gender = 1 then 1 END) as boys_present,
COUNT(CASE WHEN a.in_attendance = 1 and b.gender = 2 then 1 END) as girls_present,
COUNT(CASE WHEN a.in_attendance = 0 and b.gender = 1 then 1 END) as boys_absent,
COUNT(CASE WHEN a.in_attendance = 0 and b.gender = 2 then 1 END) as girls_absent,
COUNT(CASE WHEN b.gender = 2 then 1 END) as girls_total,
COUNT(CASE WHEN b.gender = 1 then 1 END) as boys_total
from session_details as e
inner join class as c
on c.id = e.class_id
inner join school as d
on c.school_id = d.id
inner join attendance_student as a
on e.id = a.session_details_id
inner join student as b
on a.student_id = b.id
group by c.school_id;
Image 1 shows the results set without with group for all session that were done for each class in a school. This returns correct time duration.
Image 2 shows the result set with group for all session that we done for each class in a school.
When running query 2, whereby which is an extension of query one for adding the student profile and the total no of students who were in attendance.
When running query 2,without grouping by shool_id i get the following results
Note
-I have tried to change the time to seconds then do the division then convert to minutes which return the wrong total.
sum((TIME_TO_SEC(e.time_finish) - TIME_TO_SEC(e.time_start)))/60 as duration
-I have also tried to do a sum for the time finish in second, subtract the finish and start time then divide the total
-Am also in doubt of how am doing my inner joins, and maybe the problem lies in there, since once i introduce the inner joins to students i get the errors. Other totals are working ok except for my finish and start time which are time data type on the database.
Here is a link to the related tables.
Kindly assit on how best to go about doing a correct calculation for the duration once i inner join and group the tables. :)
http://sqlfiddle.com/#!9/36bb8/2
If I understood all the details, the problem is in the group by. You must group by every field with no aggregation function (like SUM or COUNT). Using your second SQL query you change the group by like this :
select
a.session_details_id,c.class_name,c.school_id,d.school_name,
e.class_id,e.session_date,e.time_finish,e.time_start,
SUM((TIME_TO_SEC(e.time_finish) - TIME_TO_SEC(e.time_start))/60) as session_duration,
COUNT(CASE WHEN a.in_attendance = 1 and b.gender = 1 then 1 END) as boys_present,
COUNT(CASE WHEN a.in_attendance = 1 and b.gender = 2 then 1 END) as girls_present,
COUNT(CASE WHEN a.in_attendance = 0 and b.gender = 1 then 1 END) as boys_absent,
COUNT(CASE WHEN a.in_attendance = 0 and b.gender = 2 then 1 END) as girls_absent,
COUNT(CASE WHEN b.gender = 2 then 1 END) as girls_total,
COUNT(CASE WHEN b.gender = 1 then 1 END) as boys_total
from session_details as e
inner join class as c
on c.id = e.class_id
inner join school as d
on c.school_id = d.id
inner join attendance_student as a
on e.id = a.session_details_id
inner join student as b
on a.student_id = b.id
group by a.session_details_id,c.class_name,c.school_id,d.school_name,
e.class_id,e.session_date,e.time_finish,e.time_start
But, then, the SUM in the session_duration calculation, add the total duration for each student, so you need to make calculation of session_duration without aggregation function:
select
a.session_details_id,c.class_name,c.school_id,d.school_name,
e.class_id,e.session_date,e.time_finish,e.time_start,
(TIME_TO_SEC(e.time_finish) - TIME_TO_SEC(e.time_start))/60 as session_duration,
COUNT(CASE WHEN a.in_attendance = 1 and b.gender = 1 then 1 END) as boys_present,
COUNT(CASE WHEN a.in_attendance = 1 and b.gender = 2 then 1 END) as girls_present,
COUNT(CASE WHEN a.in_attendance = 0 and b.gender = 1 then 1 END) as boys_absent,
COUNT(CASE WHEN a.in_attendance = 0 and b.gender = 2 then 1 END) as girls_absent,
COUNT(CASE WHEN b.gender = 2 then 1 END) as girls_total,
COUNT(CASE WHEN b.gender = 1 then 1 END) as boys_total
from session_details as e
inner join class as c
on c.id = e.class_id
inner join school as d
on c.school_id = d.id
inner join attendance_student as a
on e.id = a.session_details_id
inner join student as b
on a.student_id = b.id
group by a.session_details_id,c.class_name,c.school_id,d.school_name,
e.class_id,e.session_date,e.time_finish,e.time_start
If you run this query on SQLFiddle you provide, your results are:
-- Edited --
After your comments I'll try again ;)
If you strip off class_id, session_date, time_start, time_finish to only get totals by school, this query will do the work:
select
c.school_id, sc.school_name,
sum((TIME_TO_SEC(sd.time_finish) - TIME_TO_SEC(sd.time_start))/60) as session_duration,
sum(stc.boys_present) boys_present, sum(stc.girls_present) girls_present,
sum(stc.boys_absent) boys_absent, sum(stc.girls_absent) girls_absent,
sum(stc.boys_total) boys_total, sum(stc.girls_total) girls_total
from session_details sd
inner join (
select a.session_details_id,
COUNT(CASE WHEN a.in_attendance = 1 and s.gender = 1 then 1 END) as boys_present,
COUNT(CASE WHEN a.in_attendance = 1 and s.gender = 2 then 1 END) as girls_present,
COUNT(CASE WHEN a.in_attendance = 0 and s.gender = 1 then 1 END) as boys_absent,
COUNT(CASE WHEN a.in_attendance = 0 and s.gender = 2 then 1 END) as girls_absent,
COUNT(CASE WHEN s.gender = 2 then 1 END) as girls_total,
COUNT(CASE WHEN s.gender = 1 then 1 END) as boys_total
from attendance_student a
inner join student s
on a.student_id = s.id
group by a.session_details_id
) stc
on sd.id = stc.session_details_id
inner join class c
on sd.class_id = c.id
inner join school sc
on c.school_id = sc.id
group by c.school_id, sc.school_name
Here I use a different approach making a subquery (maybe you prefer save as a view) to calculate student assistance totals.
First I count the students for each session using only two tables, attendance_student and student. Results are grouped by th ID os the session, so I have students by session. This query can be saved as a view for readability.
select a.session_details_id,
COUNT(CASE WHEN a.in_attendance = 1 and s.gender = 1 then 1 END) as boys_present,
COUNT(CASE WHEN a.in_attendance = 1 and s.gender = 2 then 1 END) as girls_present,
COUNT(CASE WHEN a.in_attendance = 0 and s.gender = 1 then 1 END) as boys_absent,
COUNT(CASE WHEN a.in_attendance = 0 and s.gender = 2 then 1 END) as girls_absent,
COUNT(CASE WHEN s.gender = 2 then 1 END) as girls_total,
COUNT(CASE WHEN s.gender = 1 then 1 END) as boys_total
from attendance_student a
inner join student s
on a.student_id = s.id
group by a.session_details_id
) stc
After that I join this results with session_details to calculate session_duration for each session. Our resultset now has a session_details_id, session_duration and the count of students (one row for each session).
select
sd.id as session_id,
(TIME_TO_SEC(sd.time_finish) - TIME_TO_SEC(sd.time_start))/60 as session_duration,
sum(stc.boys_present) boys_present, sum(stc.girls_present) girls_present,
sum(stc.boys_absent) boys_absent, sum(stc.girls_absent) girls_absent,
sum(stc.boys_total) boys_total, sum(stc.girls_total) girls_total
from session_details sd
inner join (
select a.session_details_id,
COUNT(CASE WHEN a.in_attendance = 1 and s.gender = 1 then 1 END) as boys_present,
COUNT(CASE WHEN a.in_attendance = 1 and s.gender = 2 then 1 END) as girls_present,
COUNT(CASE WHEN a.in_attendance = 0 and s.gender = 1 then 1 END) as boys_absent,
COUNT(CASE WHEN a.in_attendance = 0 and s.gender = 2 then 1 END) as girls_absent,
COUNT(CASE WHEN s.gender = 2 then 1 END) as girls_total,
COUNT(CASE WHEN s.gender = 1 then 1 END) as boys_total
from attendance_student a
inner join student s
on a.student_id = s.id
group by a.session_details_id
) stc
on sd.id = stc.session_details_id
We want to sum results by school so we need add to more tables, class and school. We don't really need class table to show any data but an intermediate table to get school data.

Complex querying on table with multiple userids

I have a table like this:
score
id week status
1 1 0
2 1 1
3 1 0
4 1 0
1 2 0
2 2 1
3 2 0
4 2 0
1 3 1
2 3 1
3 3 1
4 3 0
I want to get all the id's of people who have a status of zero for all weeks except for week 3. something like this:
Result:
result:
id w1.status w2.status w3.status
1 0 0 1
3 0 0 1
I have this query, but it is terribly inefficient on larger datasets.
SELECT w1.id, w1.status, w2.status, w3.status
FROM
(SELECT s.id, s.status
FROM score s
WHERE s.week = 1) w1
LEFT JOIN
(SELECT s.id, s.status
FROM score s
WHERE s.week = 2) w2 ON w1.id=w2.id
LEFT JOIN
(SELECT s.id, s.status
FROM score s
WHERE s.week = 3) w3 ON w1.id=w3.id
WHERE w1.status=0 AND w2.status=0 AND w3.status=1
I am looking for a more efficient way to calculate the above.
select id
from score
where week in (1, 2, 3)
group by id
having sum(
case
when week in (1, 2) and status = 0 then 1
when week = 3 and status = 1 then 1
else 0
end
) = 3
Or more generically...
select id
from score
group by id
having
sum(case when status = 0 then 1 else 0 end) = count(*) - 1
and min(case when status = 1 then week else null end) = max(week)
You can do using not exists as
select
t1.id,
'0' as `w1_status` ,
'0' as `w2_status`,
'1' as `w3_status`
from score t1
where
t1.week = 3
and t1.status = 1
and not exists(
select 1 from score t2
where t1.id = t2.id and t1.week <> t2.week and t2.status = 1
);
For better performance you can add index in the table as
alter table score add index week_status_idx (week,status);
In case of static number of weeks (1-3), group_concat may be used as a hack..
Concept:
SELECT
id,
group_concat(status) as totalStatus
/*(w1,w2=0,w3=1 always!)*/
FROM
tableName
WHERE
totalStatus = '(0,0,1)' /* w1=0,w2=1,w3=1 */
GROUP BY
id
ORDER BY
week ASC
(Written on the go. Not tested)
SELECT p1.id, p1.status, p2.status, p3.status
FROM score p1
JOIN score p2 ON p1.id = p2.id
JOIN score p3 ON p2.id = p3.id
WHERE p1.week = 1
AND p1.status = 0
AND p2.week = 2
AND p2.status = 0
AND p3.week = 3
AND p3.status = 1
Try this, should work

How to use user variable as counter with inner join queries that contains GROUP BY statement?

I have 2 tables odds and matches :
matches : has match_id and match_date
odds : has id, timestamp, result, odd_value, user_id, match_id
I had a query that get the following information from those tables for each user:
winnings : the winning bets for each user. (when odds.result = 1)
loses : the lost bets for each user.(when odds.result != 1)
points : the points of each user.(the sum of the odds.odd_value) for each user.
bonus : for each continuous 5 winnings i want to add extra bonus to this variable. (for each user)
How to calculate bonus?
I tried to use this query and I faced a problem : (you can check it here SQL Fiddle)
the calculated bonus are not right for all the users :
first user:(winnings:13, bonus=2).
second user:(winnings:8, bonus=2)bonus here should be 1.
third user:(winnings:14, bonus=3)bonus here should be 2.
why does the query not calculate the bonus correctly?
select d.user_id,
sum(case when d.result = 1 then 1 else 0 end) as winnings,
sum(case when d.result = 2 then 1 else 0 end) as loses,
sum(case when d.result = 1 then d.odd_value else 0 end) as points,
f.bonus
FROM odds d
INNER JOIN
(
SELECT
user_id,SUM(CASE WHEN F1=5 THEN 1 ELSE 0 END) AS bonus
FROM
(
SELECT
user_id,
CASE WHEN result=1 and #counter<5 THEN #counter:=#counter+1 WHEN result=1 and #counter=5 THEN #counter:=1 ELSE #counter:=0 END AS F1
FROM odds o
cross join (SELECT #counter:=0) AS t
INNER JOIN matches mc on mc.match_id = o.match_id
WHERE MONTH(STR_TO_DATE(mc.match_date, '%Y-%m-%d')) = 2 AND
YEAR(STR_TO_DATE(mc.match_date, '%Y-%m-%d')) = 2015 AND
(YEAR(o.timestamp)=2015 AND MONTH(o.timestamp) = 02)
) Temp
group by user_id
)as f on f.user_id = d.user_id
group by d.user_id
I am not sure how your result related to matches table,
you can add back WHERE / INNER JOIN clause if you need.
Here is link to fiddle
and the last iteration according to your comments:
And here is a query:
SET #user:=0;
select d.user_id,
sum(case when d.result = 1 then 1 else 0 end) as winnings,
sum(case when d.result = 2 then 1 else 0 end) as loses,
sum(case when d.result = 1 then d.odd_value else 0 end) as points,
f.bonus
FROM odds d
INNER JOIN
(
SELECT
user_id,SUM(bonus) AS bonus
FROM
(
SELECT
user_id,
CASE WHEN result=1 and #counter<5 AND #user=user_id THEN #counter:=#counter+1
WHEN result=1 and #counter=5 AND #user=user_id THEN #counter:=1
WHEN result=1 and #user<>user_id THEN #counter:=1
ELSE
#counter:=0
END AS F1,
#user:=user_id,
CASE WHEN #counter=5 THEN 1 ELSE 0 END AS bonus
FROM odds o
ORDER BY user_id , match_id
) Temp
group by user_id
)as f on f.user_id = d.user_id
group by d.user_id

GROUP BY on table returning incorrect counts in MySQL with LEFT JOIN

I am trying to return multiple counts and averages from multiple tables sorting by gender and am getting incorrect data. I understand that the following is incorrect, but I am unsure of how to fix it. (Edit: Problem with group by gender. See below.)
Here is the query:
SELECT c.gender AS 'Gender',
COUNT(DISTINCT mr.mailing_recipient_id) AS 'Mailing Recipients',
(SELECT COUNT(DISTINCT CASE WHEN mrc.mailing_recipient_click_type_id = 2 THEN 1 ELSE 0 END) ) AS 'Open Total',
AVG(CASE WHEN mrc.mailing_recipient_click_type_id = 2 THEN 1 ELSE 0 END) AS 'Avg Open',
(SELECT COUNT(DISTINCT CASE WHEN mrc.mailing_recipient_click_type_id = 1 THEN 1 ELSE 0 END) ) AS 'Click Total',
AVG(CASE WHEN mrc.mailing_recipient_click_type_id = 1 THEN 1 ELSE 0 END) AS 'Avg Click',
COUNT(DISTINCT ca.cons_action_contribution_id) AS Donations,
AVG(ca.transaction_amt) AS 'Avg Donation Amt'
FROM ((mailing m
LEFT JOIN mailing_recipient mr ON m.mailing_id = mr.mailing_id)
LEFT JOIN mailing_recipient_click mrc ON mr.mailing_recipient_id = mrc.mailing_recipient_id
LEFT JOIN cons_action_contribution ca ON mr.cons_id = ca.cons_id
LEFT JOIN cons c ON c.cons_id = ca.cons_id)
WHERE m.mailing_id = 1
AND gender IS NOT NULL
GROUP BY c.gender;
Here is the table which would be correct if the totals in the fields were correct:
GENDER Mailing Recipient Open Total Avg Open Click Total Avg Click Donations Avg Amt
F 105 2 0.5000 2 0.5000 105 22.5000
M 98 2 0.5000 2 0.5000 98 18.8780
EDIT: Here is an example of what I am hoping to achieve. I am certain that the above values are being repeated. The below values are just examples of what I am expecting:
GENDER Mailing Recipient Open Total Avg Open Click Total Avg Click Donations Avg Amt
F 105 8 0.0761 4 0.0380 2 22.5000
M 98 2 0.0204 1 0.0102 1 18.8000
Edit:
After playing around a bit, I thought that I had discovered that the joining the cons table was what is giving me problematic returns, but the problem is with GROUP BY when using gender. To illustrate, this query (which is grouped by mailing name instead of gender) works beautifully.
select m.mailing_name AS 'mailing',
COUNT(DISTINCT mr.mailing_recipient_id) AS 'Mailing Recipients',
SUM(CASE
when mrc.mailing_recipient_click_type_id = 2 THEN 1
END)
AS 'Open Total',
AVG(CASE
WHEN mrc.mailing_recipient_click_type_id = 2 THEN 1
ELSE 0
END) AS 'Avg Open',
SUM(CASE
WHEN mrc.mailing_recipient_click_type_id = 1 THEN 1
END)
AS 'Click Total',
AVG(CASE
WHEN mrc.mailing_recipient_click_type_id = 1 THEN 1
ELSE 0
END) AS 'Avg Click',
COUNT(ca.cons_action_contribution_id) AS Donations,
AVG(ca.transaction_amt) AS 'Avg Donation Amt'
FROM
mailing m
LEFT JOIN mailing_recipient mr ON m.mailing_id = mr.mailing_id
LEFT JOIN mailing_recipient_click mrc
ON mr.mailing_recipient_id = mrc.mailing_recipient_id
LEFT JOIN cons_action_contribution ca ON mr.cons_id = ca.cons_id
LEFT JOIN cons c ON mr.cons_id = c.cons_id
WHERE m.mailing_id = 1
GROUP BY m.mailing_name;
The statement is identical with the exception of the first and last lines.
Try this:
I'm not sure what you mean by Avg Open and Avg Click.
SELECT c.gender AS 'Gender',
COUNT(DISTINCT mr.mailing_recipient_id) AS 'Mailing Recipients',
SUM(CASE WHEN mrc.mailing_recipient_click_type_id = 2 THEN 1 ELSE 0 END) AS 'Open Total',
AVG(CASE WHEN mrc.mailing_recipient_click_type_id = 2 THEN 1 ELSE 0 END) AS 'Avg Open',
SUM(CASE WHEN mrc.mailing_recipient_click_type_id = 1 THEN 1 ELSE 0 END) AS 'Click Total',
AVG(CASE WHEN mrc.mailing_recipient_click_type_id = 1 THEN 1 ELSE 0 END) AS 'Avg Click',
COUNT(DISTINCT ca.cons_action_contribution_id) AS Donations,
AVG(ca.transaction_amt) AS 'Avg Donation Amt'
FROM mailing m
LEFT JOIN mailing_recipient mr ON m.mailing_id = mr.mailing_id
LEFT JOIN mailing_recipient_click mrc ON mr.mailing_recipient_id = mrc.mailing_recipient_id
LEFT JOIN cons_action_contribution ca ON mr.cons_id = ca.cons_id
LEFT JOIN cons c ON c.cons_id = ca.cons_id
WHERE m.mailing_id = 1
AND gender IS NOT NULL
GROUP BY c.gender;
I also think that mrc.mailing_recipient_click_type_id = 2 means open and mrc.mailing_recipient_click_type_id = 1 mean click seems strange to me. I would expect this data to be exclusive and stored in two different fields.