2 where conditions from 1 column SQL [duplicate] - mysql

This question already has answers here:
How can I get multiple counts with one SQL query?
(12 answers)
Closed 2 months ago.
I am trying to see 2 conditional columns using the WHERE clause from 1 column.
For example:
I have a dataset where I have a long list of calls. I would like to see two different columns where the first column shows a count of all those calls who are equal or longer that 0 seconds and a second column that shows a count of all those calls that are equal or longer to 120 seconds.
That is my first query:
SELECT distinct year(date) Year, monthname(date) as Month, count(calls) Leads
FROM database.calls
where duration >= 120
and year(date) = 2022
group by month(date)
order by max(date);
second query:
(The only difference it's on the 3rd line where duration is equal to 0)
SELECT distinct year(date) Year, monthname(date) as Month, count(calls) Leads
FROM database.calls
where duration >= 0
and year(date) = 2022
group by month(date)
order by max(date);
Expected Result:
Year
Month
Calls(0sec)
Calls(120sec)
2022
January
654
521
2022
February
895
465
2022
March
562
321

For obtaining conditional sums you can use conditional aggregation: specify a condition inside your aggregate function, so that it aggregates only the eligible values.
SELECT YEAR(date) AS Year_,
MONTHNAME(date) AS Month_,
SUM(IF(duration > 0, 1, 0)) AS Calls0Sec,
SUM(IF(duration > 120, 1, 0)) AS Calls120Sec
FROM database.calls
WHERE YEAR(date) = 2022
GROUP BY YEAR(date), MONTHNAME(date)
ORDER BY MAX(date);
Note: you need to add every selected and non-aggregated field inside the GROUP BY clause, otherwise you can expect either DBMS errors or wrong data.

Related

2 Counts Statements in MySQL [duplicate]

This question already has answers here:
Is it possible to GROUP BY multiple columns using MySQL?
(7 answers)
Closed last month.
I am trying to see the number of products sold to different companies by month and year.
For example:
I have a dataset where I have a long list of products. I would like to see two different columns where the first column shows a count of all those products and a second column that shows the company that was sold to by month and year
That is my query:
SELECT MONTHNAME(date) AS Month, COUNT(*), company
FROM database.products
WHERE YEAR(date) = '2022'
GROUP BY MONTH(date)
WITH ROLLUP);
Expected Result:
Year
Month
Products
Company
2022
January
654
walmart
2022
January
895
Winco
2022
February
562
Ross
2022
February
456
Best Buy
Just add the rest of the fields...?
SELECT YEAR(date) AS Year, MONTHNAME(date) AS Month, COUNT(*), company
FROM database.products
WHERE YEAR(date) = '2022'
GROUP BY YEAR(date), MONTH(date), company
WITH ROLLUP

Group By rows where value equals 0 or non-existent rows in mysql?

I have a simple piece of SQL code where I am trying to get the monthly averages of numbers. But the problem I am running into is if any number within any given month is 0 then the average returned is 0 or if there are any rows that don't exist with any given month then there are no values returned at all for that month. Hopefully, someone can give me some insight as to what I am doing wrong.
GROUP BY 1 = a.metric and GROUP BY 2 = a.report_dt within the subquery
I have tried inserting the missing rows with a value of 0, but as I said it will return the averaged value as 0 as well.
SELECT a.report_dt - INTERVAL 1 DAY AS 'Date',
a.metric,
a.num
FROM (SELECT *
FROM reporting.tbl_bo_daily_levels b
WHERE b.report_dt = reporting.func_first_day(b.report_dt)
AND b.report_dt > DATE_SUB(NOW(), INTERVAL 12 MONTH)
GROUP BY 1,2
)a;
My expected results are to get the average numbers of each month even if there are non-existent rows within the specified date range or even if there zeroes as values.
You need a relation of all the months you want to span. This can be made ad hoc with UNION ALL. Then left join the data on the months GROUP BY the month and the metric and get avg(num).
SELECT m.year,
m.month,
l.metric,
coalesce(avg(l.num), 0)
FROM (SELECT 2017 year,
12 month
UNION ALL
SELECT 2018 year,
1 month
UNION ALL
SELECT 2018 year,
2 month
...
SELECT 2018 year,
11 month
UNION ALL
SELECT 2018 year,
12 month) months m
LEFT JOIN reporting.tbl_bo_daily_levels l
ON year(l.report_dt) = m.year
AND month(l.report_dt) = m.month;
GROUP BY m.year,
m.month,
l.metric;
(Change the second parameter to coalesce if you want any other number than 0 if there are no numbers for a month. Or don't use coalesce() at all if you want NULL in such cases.)

How to select the compute the range value of a given date?

I have this table below. I want to count and select the values within a month range.
Here's my query
select count(*) as c, monthname(file_date) as mn
from baguio_patrolcase
where monthname(file_date) between 'January' and 'July'
group by monthname(file_date)
order by file_date
What I want to achive is that it will also count and select the values from February an June. How will I do this?
When you convert the date to a month name, you are comparing strings. Here are two options to do what you want:
where month(file_date) between 2 and 6
where file_date >= '2015-02-01' and file_date < '2015-07-01'
The second is better, because it allows the engine to use an index on file_date (if available).
Also, between keeps the end values (it is inclusive). So, if you want February through June, then use those months, rather than 1 and 7.
What I have understood, you can use in clause:
select count(*) as c, monthname(file_date) as mn
from baguio_patrolcase
where monthname(file_date) in('January', 'July')
group by monthname(file_date)
order by file_date
Add the name of all the required months in the in clause.
You can see the SQLFiddle Demo here.

MYSQL avoid SELECT computation if multiplying by ZERO

I am doing a SELECT from a MYSQL table
Table looks like this
year tour starts scoring_avg
1990 EUR 5 71.56
1990 USA 6 0.0
1991 EUR 12 71.21
1991 USA 8 69.23
I am doing a SELECT like so
SELECT
year,
SUM(starts),
SUM(starts*scoring_avg) as scoring.avg
FROM scores
GROUP BY year
Goal is to get combined scoring average for the year, combining the EUR and USA rows for each year.
After the SELECT, I divide scoring_avg by starts. Since I added a 6 to starts from the second line, with no scoring_avg for that line, the result is not correct.
Works fine for year 1991.
Doesn't work for year 1990, since the scoring_avg for the USA row is 0.
Is there a way the SELECT can be modified to only use the ps.starts*ps.scoring_avg in the SUM where ps.scoring_avg in that row is greater than 0?
Thank you.
-- Ed
If you just want to change scoringavg, use conditional aggregation:
SELECT year, SUM(starts),
SUM(case when scoring_avg > 0 then starts*scoring_avg end) as scoring_avg
FROM scores
GROUP BY year;
However, I would suggest doing all the work in a single query and not doing any division afterwards. The following calculates the average that you want:
SELECT year, SUM(starts),
(SUM(case when scoring_avg > 0 then starts*scoring_avg end) /
SUM(scoring_avg > 0)
) as scoring_avg
FROM scores
GROUP BY year;
You may try this:
SELECT
year,
SUM(starts),
SUM(starts*scoring_avg) as scoring.avg
FROM scores
WHERE scoring_avg > 0
GROUP BY year
You could use an expression that conditionally returns either the value from the starts column, or 0 (or NULL), based on the value in the scoring_avg column. As an example:
IF(scoring_avg=0,0,starts)
That says, if scoring_avg has a value of zero (for a particular row), then return zero; otherwise, returns the value from the starts column. This is MySQL specific syntax, equivalent to the an ANSI-standard CASE expression:
CASE scoring_avg WHEN 0 THEN 0 ELSE starts END
In the context of your query:
SELECT s.year
, SUM( IF(s.scoring_avg=0,0,s.starts) ) AS `starts`
, SUM( s.starts*s.scoring_avg ) AS `scoring.avg`
, SUM( s.starts*s.scoring_avg ) /
SUM( IF(s.scoring_avg=0,0,s.starts) ) AS `scoring.avg_div_starts`
FROM scores s
GROUP BY s.year

sql multiple columns plus sum of each column

Using MySQL, I am counting the occurrence of several events (fields) over a time span of years. I then display this in columns by year. My query works perfect when grouped by year. I now want to add a final column which displays the aggregate of the years. How do I include the total of columns query?
Event 2008 2009 2010 2011 total
A 0 2 0 1 3
B 1 2 3 0 6
etc.
Here is the real query:
select
count(*) as total_docs,
YEAR(field_document_date_value) as doc_year,
field_document_facility_id_value as facility,
IF(count(IF(field_document_type_value ='LIC809',1, NULL)) >0,count(IF(field_document_type_value ='LIC809',1, NULL)),'-') as doc_type_LIC809,
IF(count(IF(field_document_type_value ='LIC9099',1, NULL)) >0,count(IF(field_document_type_value ='LIC9099',1, NULL)),'-') as doc_type_LIC9099,
IF(count(field_document_f1_value) >0,count(field_document_f1_value),'-') as substantial_compliance,
IF(count(field_document_f2_value) >0,count(field_document_f2_value),'-') as deficiencies_sited,
IF(count(field_document_f3_value) >0,count(field_document_f3_value),'-') as admin_outcome_809,
IF(count(field_document_f4_value) >0,count(field_document_f4_value),'-') as unfounded,
IF(count(field_document_f5_value) >0,count(field_document_f5_value),'-') as substantiated,
IF(count(field_document_f6_value) >0,count(field_document_f6_value),'-') as inconclusive,
IF(count(field_document_f7_value) >0,count(field_document_f7_value),'-') as further_investigation,
IF(count(field_document_f8_value) >0,count(field_document_f8_value),'-') as admin_outcome_9099,
IF(count(field_document_type_a_value) >0,count(field_document_type_a_value),'-') as penalty_type_a,
IF(count(field_document_type_b_value) >0,count(field_document_type_b_value),'-') as penalty_type_b,
IF(sum(field_document_civil_penalties_value) >0,CONCAT('$',sum(field_document_civil_penalties_value)),'-') as total_penalties,
IF(count(field_document_noncompliance_value) >0,count(field_document_noncompliance_value),'-') as total_noncompliance
from rcfe_content_type_facility_document
where YEAR(field_document_date_value) BETWEEN year(NOW()) -9 AND year(NOW())
and field_document_facility_id_value = :facility
group by doc_year
You can not GROUP row twice in a SELECT, so you can only count row in a year or in total. You can UNION two SELECT (one grouped by year, second not grouped - total) to overcome this limitation, but I think it is better to count total from year result in script if there is any.
Simplified example:
SELECT by_year.amount, years.date_year FROM
-- generating years pseudo table
(
SELECT 2008 AS date_year
UNION ALL SELECT 2009
UNION ALL SELECT 2010
UNION ALL SELECT 2011
) AS years
-- joining with yearly stat data
LEFT JOIN
(
SELECT SUM(value_field) AS amount, YEAR(date_field) AS date_year FROM data
GROUP BY YEAR(date_field)
) AS by_year USING(date_year)
-- appending total
UNION ALL SELECT SUM(value_field) AS amount, 'total' AS date_year FROM data
WITH ROLLUP is your friend:
http://dev.mysql.com/doc/refman/5.7/en/group-by-modifiers.html
Use your original query and simply add this to the last line:
GROUP BY doc_year WITH ROLLUP
That will add a final cumulative row to your query's result set.