i can't Merge two tables - mysql

i have one tables attendance
main table
i created 2 views from attendance table attend view and leaved view
view:attend
select `dbtest`.`employee`.`empId` AS `empId`,`dbtest`.`attendance`.`timeAttendnace` AS `timeAttendnace` from (`dbtest`.`employee` left join `dbtest`.`attendance` on(`dbtest`.`attendance`.`empId` = `dbtest`.`employee`.`empId` and `dbtest`.`attendance`.`statusAttendnace` = 'In'))
view:leaved
select `dbtest`.`employee`.`empId` AS `empId`,`dbtest`.`attendance`.`timeAttendnace` AS `timeAttendnace` from (`dbtest`.`employee` left join `dbtest`.`attendance` on(`dbtest`.`attendance`.`empId` = `dbtest`.`employee`.`empId` and `dbtest`.`attendance`.`statusAttendnace` = 'Out'))
after that i used this code to merge attend and leaved view
select `attend`.`empId` AS `empId`,`attend`.`timeAttendnace` AS `clockIn`,`leaved`.`timeAttendnace` AS `clockOut` from (`dbtest`.`attend` join `dbtest`.`leaved` on(`attend`.`empId` = `leaved`.`empId`)) group by `attend`.`timeAttendnace` order by `attend`.`empId`
the result was like this
result
i need each employee has attend time and leaved time in same day

This following query will return you employee wise daily In and Out Time in a single row.
SELECT
cast(TimeAttendence AS DATE),
empid,
MIN(CASE WHEN StatusAttendence = 'In' THEN TimeAttendence END) InTime,
MAX(CASE WHEN StatusAttendence = 'Out' THEN TimeAttendence END) OutTime
FROM main_table
GROUP BY cast(TimeAttendence AS DATE),empid

Related

Is it possible that each condition in "case when" has a different table?

I have a query like below
select
COALESCE(Clinic,'total') as Clinic,
sum(Non_Billable) as Non_Billable,
sum(initial_Non_Billable) as initial_Non_Billable,
sum(Non_Billable)/NULLIF(sum(initial_Non_Billable),0) as Non_Billable_initial_revenue
FROM (
select
businesses.label as Clinic,
sum(CASE
WHEN appointment_types.category IN (
'Others',
'Non-Billable')
and appointment_types.name like '%initial%'
then invoices.net_amount ELSE 0 END)
as Non_Billable,
count(CASE
WHEN appointment_types.category IN (
'Others',
'Non-Billable')
and appointment_types.name like '%initial%'
then appointment_types.name ELSE null END)
as initial_Non_Billable
FROM
individual_appointments
INNER join appointment_types on
appointment_types.id = individual_appointments.appointment_type_id
inner join invoices on
invoices.appointment_id = individual_appointments.id
inner join businesses on
businesses.id = individual_appointments.business_id
group by
businesses.label,
appointment_types.name,
appointment_types.category,
invoices.net_amount
)x
group by
ROLLUP(Clinic);
is it possible for each condition in "case when then" to have a different table?
example: for "Non_Billable" only want from individual_appointment, appointment_types, invoices and businesses table only.
while "initial_Non_Billable" only wants from individual_appointment, appointment_types, and businesses table.
can it be like that?
If possible, how? can anyone give an example?
From what I see, I suppose the problem here is that there can be many invoices per appointment, so when you join invoices you get appointments multifold which also multiplies your counts.
You don't really want to join invoices hence, but invoice sums. I.e. aggregate before joining.
Then, you are only interested in non-billable appointments, so you can put that criteria into your ON clauses and outer join in order to get clinics without such appointments.
select
coalesce(b.label, 'total') as clinic,
coalesce(sum(i.total_net_amount), 0) as initial_non_billable_sum,
count(at.id) as initial_non_billable_count,
avg(i.total_net_amount) as initial_non_billable_average
from businesses b
left join individual_appointments ia on ia.business_id = b.id
left join appointment_types at on at.id = ia.appointment_type_id
and at.category in ('others', 'non-billable')
and at.name like '%initial%'
left join
(
select appointment_id, sum(net_amount) as total_net_amount
from invoices
group by appointment_id
) i on i.appointment_id = ia.id
group by rollup(b.label)
order by b.label nulls last;

MySQL - Joining same table twice, parent sum column value getting duplicated

I'm just 3 months of experience in MySQL. Here I'm trying to generate a report based on log and part table. When trying to join the "Part" table twice, the "Log" table Quantity gets doubled. Kindly let me know where I'm doing wrong.
Log Table
Part Table
Expected Report
Query Used
SELECT
report.*,
(SUM(report.quantity)) AS totalQuantity,
normalPart.price AS normalPrice,
premiumPart.price AS premiumPrice
FROM
log AS report
LEFT JOIN
(SELECT
*
FROM
part AS normalPart
WHERE
normalPart.type = 'normal'
GROUP BY normalPart.partNumber , normalPart.genId) AS normalPart ON report.partNumber = normalPart.partNumber
AND report.genId = normalPart.genId
AND normalPart.cat = report.fromCat
LEFT JOIN
(SELECT
*
FROM
part AS premiumPart
WHERE
premiumPart.type = 'premium'
GROUP BY premiumPart.partNumber , premiumPart.genId) AS premiumPart ON report.partNumber = premiumPart.partNumber
AND report.genId = premiumPart.genId
AND premiumPart.cat = report.toCat;
Query Result
This answers the original version of the question.
Aggregate before you join:
select l.*, p.normal_price, p.premium_price
from (select genid, partnumber, sum(quantity) as quantity
from log
group by genid, partnumber
) l left join
(select partnumber, genid,
max(case when type = 'normal' then price end) as normal_price,
max(case when type = 'premium' then price end) as premium_price
from part
group by partnumber, genid
) p
on p.partnumber = l.partnumber and p.genid = l.genid

MySQL query returning only one row because of SUM function in it

I am trying to create an advertisement query where I want to fetch data of all the impressions per advertisement. One user can have multiple advertisements and impressions will be counted in a table on per day basis. So for each day I will have one different row. Here is how my query currently looks like.
SELECT
eac.id,
eac.gender,
eac.start_date,
eac.end_date,
eac.ad_image_path,
eac.ad_link,
eac.requestfrom,
eac.traffic,
eac.registertype,
eacr.region_id,
eac.active,
eac.impression,
eac.center_image_path,
eac.bottom_image_path,
eac.approved_by,
er.name as country_name,
eac.budget,
sum(budget/ (DATEDIFF(end_date,start_date)) *1000) as daily_imp,
eaa.impression_count,
eac.customer_id,
eaa.created_at
FROM
`enrich_advert_customer` eac
JOIN `enrich_advert_customer_regions` eacr ON eac.id = eacr.advert_customer_id
JOIN `enrich_regions` er ON er.id = eacr.region_id
LEFT JOIN `enrich_advert_abstract` eaa on eac.id = eaa.advert_customer_id
WHERE
eac.requestfrom ='web' AND
eac.registertype = 'paid' AND
eac.active = 1 AND
eac.approved_by = 1 AND
eac.gender ='male' AND
er.name = 'india' AND
eac.start_date <= '2018-11-5' AND
eac.end_date >= '2018-11-10'
But the problem here is if I am using
sum(budget/ (DATEDIFF(end_date,start_date)) *1000) as daily_imp
this then its returning only one row at a time.
If you can suggest where I am making a mistake that will be helpful.
Thank you!
You need to add group by clause and others column in there as you applyied aggregation
SELECT eac.id,eac.gender,eac.start_date,eac.end_date,eac.ad_image_path,eac.ad_link,eac.requestfrom,eac.traffic,eac.registertype,eacr.region_id,eac.active,eac.impression,eac.center_image_path,eac.bottom_image_path,eac.approved_by,er.name as country_name,eac.budget,sum(budget/ (DATEDIFF(end_date,start_date)) *1000) as daily_imp ,eaa.impression_count,eac.customer_id,eaa.created_at
FROM
`enrich_advert_customer` eac
JOIN
`enrich_advert_customer_regions` eacr
ON eac.id = eacr.advert_customer_id
JOIN
`enrich_regions` er
ON er.id = eacr.region_id
LEFT JOIN
`enrich_advert_abstract` eaa
on eac.id = eaa.advert_customer_id
WHERE eac.requestfrom ='web' AND
eac.registertype = 'paid' AND
eac.active = 1 AND
eac.approved_by = 1 AND
eac.gender ='male' AND
er.name = 'india' AND
eac.start_date <= '2018-11-5' AND
eac.end_date >= '2018-11-10'
group by eac.id,eac.gender,eac.start_date,eac.end_date,eac.ad_image_path,eac.ad_link,eac.requestfrom,eac.traffic,eac.registertype,eacr.region_id,eac.active,eac.impression,eac.center_image_path,eac.bottom_image_path,eac.approved_by,er.name,eac.budget, eaa.impression_count,eac.customer_id,eaa.created_at

mysql COUNT function on two or more columns as per true column value

I am trying to count the number of times the two columns have their assigned value appears. The sql statement I have so far outputs wrong results. Take a look:
SELECT
UPPER(school.district) AS District_name,
COUNT(DISTINCT task1.wp_status) AS Status_New,
COUNT(task1.wp_type) AS Type_Bolehole
FROM school
RIGHT OUTER JOIN task1 ON school.s_name=task1.name
WHERE task1.wp_status="New" OR task1.wp_type="Bolehole"
GROUP BY district AND task1.wp_status="New" AND task1.wp_type="Bolehole"
ORDER BY district;
The two tables am using are as below
School
s_name district
matero lusaka
kema lusaka
naka kabwe
task1
name wp_status wp_type
matero New Bolehole
kema New Bolehole
naka New ProtectedWell
expected output
D_Name Status_New Type_Bolehole
KABWE 1 2
LUSAKA 2 0
I would recommend writing the query like this:
SELECT UPPER(s.district) AS District_name,
SUM(t1.wp_status = 'New') AS Status_New,
SUM(t1.wp_type = 'Bolehole') AS Type_Bolehole
FROM school s JOIN
task1 t1
ON s.s_name = t1.name
WHERE t1.wp_status = 'New' or t1.wp_type = 'Bolehole'
GROUP BY UPPER(s.district)
ORDER BY District_Name;
This makes the following changes:
Table aliases are introduced to make the query easier to read and write.
The join is changed to an inner join. You are selecting on one table and aggregating by the other, so it seems that the query expects a match in both tables.
The group by is based on the actual expression used in the select.
Conditional aggregation is used to get the two columns of counts.
Note: This assumes that the sample results in the question are not correct.
you dont need a right join.. all you need is one conditional sum of the rows
SELECT
UPPER(s.district) AS District_name,
SUM(case when t.wp_status = 'New' then 1 else 0 end) AS Status_New,,
SUM(case when t.wp_type = 'Bolehole' then 1 else 0 end) AS Type_Bolehole
FROM school s
LEFT JOIN task1 t ON s.s_name=t.name
WHERE t.wp_status = 'New' or t.wp_type = 'Bolehole'
GROUP BY District_name
ORDER BY District_name;
DEMO
Try this
SELECT UPPER(school.district) AS District_name,
sum( task1.wp_status ="New") AS Status_New,
sum(task1.wp_type="Bolehole") AS Type_Bolehole FROM school
RIGHT OUTER JOIN task1 ON school.s_name=task1.name
WHERE task1.wp_status="New" OR task1.wp_type="Bolehole"
GROUP BY district
ORDER BY district;
Also in your expected result set bolehole count for firt row should be 0 because task naka don't have type of bolehole
Fiddle Demo

count multiple in one statement

i have a table with data title and date of the data inserted.
and right now i want to do count to make the statistic out of it.
can i do multiple count in one sql statement?
like from, the column date, i want to count how many on this month, and how many in this year, until month selected. is it possible? if yes, how?
this is what i have come up, for now.
SELECT a.trigger_type_code
, c.trigger_name
, COUNT(*) AS number
FROM issue_trigger a
INNER JOIN cs_issue b
ON b.issue_id = a.issue_id
INNER JOIN ref_trigger_type c
ON c.trigger_type_code = a.trigger_type_code
WHERE MONTH(b.created_date) = '05'
AND YEAR(b.created_date) = '2011'
GROUP BY trigger_type_code,trigger_name
by this is only for one count.help.:(
You could use a case:
select sum(case when MONTH(b.created_date) = '05'
AND YEAR(b.created_date) = '2011' then 1 end) as Count_2011_05
, sum(case when YEAR(b.created_date) = '2011'
then 1 end) as Count_2011
from ... etc ...
I think you could go like this:
SELECT
a.trigger_type_code,
c.trigger_name,
COUNT(MONTH(b.created_date) < 5 OR NULL) AS before_the_month,
COUNT(MONTH(b.created_date) = 5 OR NULL) AS in_the_month
FROM issue_trigger a
INNER JOIN cs_issue b
ON b.issue_id = a.issue_id
INNER JOIN ref_trigger_type c
ON c.trigger_type_code = a.trigger_type_code
WHERE YEAR(b.created_date) = 2011
GROUP BY a.trigger_type_code, c.trigger_name