MySQL: How do I find the average for specific rows? - mysql

I have a sales table and need to calculate the average call time when a case is met. I'm doing the query for each day of the month.
My query is
SELECT AVG(case when (outcome= 'Sale1' or outcome='Sale2') then call_length else 0 end) as avg_call_length
FROM SALES
WHERE year(call_date)='2018' and month(call_date)='7' and day(call_date)='30'
Lets say I have 100 records then avg_call_length is divided by 100 instead of how many records are Sale1 or Sale2. How do I write the correct query?

Delete the case and move the condition to the where:
SELECT AVG(call_length) as avg_call_length
FROM SALES
WHERE date(call_date) = '2018-07-30'
AND outcome IN ('Sale1', 'Sale2')
Note the simpler way of coding the conditions.

Related

MYSQL SUM, value has to change on condition

I have a "CONTRACTS" table in which the user can select whether a Contract is "ANUAL" or "MONTHLY" (working on MariaDB/phpmyadmin)
The data is stored in the following manner:
CONTRACT
PERIOD
CICLE
SALE PRICE
CATEGORY
001
1
YEARLY
12000
CAT1
002
1
MONTHLY
1000
CAT2
I want to make a report that tells me the SUM of monthly contracts by CATEGORY
RIGHT NOW, THIS QUERY BELOW WORKS but its useless, since its doing SUM of "yearly" contracts along with monthly contracts
SELECT SUM(contracts.salesprice), `categories`.*
FROM `contracts`
LEFT JOIN `categories` ON `contratos`.`cat_id` = `categories`.`id_cat`
GROUP BY categorias.descripcion_cat;1
I'm a newbie and so far I was fine with INSERT, SELECT, UPDATE, DELETE;
I tried reading all documentation about CASE or IF, but I cant figure how to tell mysql to SUM based AND calculate on conditions
when CICLE = YEARLY then SALEPRICE /12 (to get the monthly value)
You were on the correct track with CASE.
The following code snippet will convert your yearly sales prices into monthly:
SUM(
CASE
WHEN contracts.cicle = 'YEARLY' THEN (contracts.salesprice / 12)
WHEN contracts.cicle = 'MONTHLY' THEN contracts.salesprice
ELSE 0
END
)
To use it in your query, simply replace your SUM(...) with that one.
To explain what it is doing, the CASE statement has several WHEN conditions. It uses the value of the first one that is true, if none are true, it will use the ELSE value (which you can change if you don't like 0). All of those resulting values are then summed up with SUM.
The benefit of CASE over IF is that CASE can be expanded as needed if you need more calculations for bi-annual, quarter, etc.

Get the max value of different sum values in sql

I have a table called "Sold_tickets" with attributes "Ticket_id" and "Date_sold". I want to find the day when the most tickets have been sold and the amount of tickets that were sold.
ticket_id date_sold
1 2017-02-15
2 2017-02-15
3 2017-02-14
In this case I want my output to look like this:
date_sold amount
2017-02-15 2
I know you can use a query like this
SELECT Count(ticket_id)
FROM Sold_tickets
WHERE date_sold = '2017-02-15';
to get an output of 2. The same can of course be done for 2017-02-14 to get an output of 1. However, then I have to manually check all the dates and compare them myself. Does a function exist (in sqlite) that counts the tickets sold for all the dates and then shows you only the maximum value?
Try using a GROUP BY aggregation query, then retain only the record having the maximum number of sales.
SELECT date_sold, COUNT(*)
FROM Sold_tickets
GROUP BY date_sold
ORDER BY COUNT(*) DESC
LIMIT 1
This solution would work well assuming that you don't have two or more dates tied for the greatest number of sales, or, if there is a tie, that you don't mind choosing just one date group.

Time Frequency of Inserts

I have data being inserted into a mysql table of the form
id companyid date
how would I find the time average frequency of inserts by companyid.
Some companies send data daily, some weekly, some every 10 days, etc.
would like a result of the form
companyid average frequency of inserts
2 every 5 days
3 every 10 days
4 every 2 days
One definition of average would be the difference between the maximum and minimum values divided by one less than the count. Something like this might be what you are looking for:
select companyid,
(case when max(date) <> min(date())
then datediff(max(date), min(date)) / (count(*) - 1)
end) as average_frequency
from table t
group by companyid;

Query to retrieve values form DB on multiple criteria

I Need to retrieve values from database to plot them in graph. For that I need to get values on criteria basis. Data matching different criteria has to be returned as different rows/ column to my query
(i.e)
I have a table called TABLEA which has a column TIME. I need to get the value based on time critreia as a result, count of rows which are matching TIME>1 and TIME<10 as a result, TIME>11 and TIME <20 as a result and so on. Is it possible to get the values in a single query. I use Mysql with JDBC.
I should plot all the counts in a graph
Thanks in advance.
select sum(case when `time` between 2 and 9 then 1 else 0 end) as count_1,
sum(case when `time` between 12 and 19 then 1 else 0 end) as count_2
from your_table
This can be done with CASE statements, but they can get kind of verbose. You may just want to rely on Boolean (true/false) logic:
SELECT
SUM(TIME BETWEEN 1 AND 10) as `1 to 10`,
SUM(TIME BETWEEN 11 and 20) as `11 to 20`,
SUM(TIME BETWEEN 21 and 30) as `21 to 30`
FROM
TABLEA
The phrase TIME BETWEEN 1 AND 10) will either returnTRUEorFALSEfor each record.TRUEbeing equivalent to1andFALSEbeing equivalent to0`, we then only need sum the results and give our new field a name.
I also made the assumption that you wanted records where 1 <= TIME <= 10 instead of 1 < TIME < 10 which you stated since, as stated, it would drop values where the TIME was 1,10,20, etc. If that was your intended result, then you can just adjust the TIME BETWEEN 1 AND 10 to be TIME BETWEEN 2 AND 9 instead.

Combine multiple room availability queries into one

I'm currently trying to optimize an database by combining queries. But I keep hitting dead ends while optimizing an room availability query.
I have a room availability table where each records states the available number of rooms per date. It's formatted like so:
room_availability_id (PK)
room_availability_rid (fk_room_id)
room_availability_date (2011-02-11)
room_availability_number (number of rooms available)
The trouble is getting a list of rooms that are available for EACH of the provided days. When I use IN() like so:
WHERE room_availability_date IN('2011-02-13','2011-02-14','2011-02-15')
AND room_availability_number > 0
If the 14th has availability 0 it still gives me the other 2 dates. But I only want that room_id when it is available on ALL three dates.
Please tell me there is a way to do this in MySQL other than querying each date/room/availability combination separately (that is what is done now :-( )
I tried all sorts of combinations, tried to use room_availability_date = ALL (...), tried some dirty repeating subqueries but to no avail.
Thank you in advance for any thoughts!
You would need to construct a query to group on the room ID and then check that there is availability on each date, which can be done using the having clause. Leaving the where clause predicate in for room_availability_date will help to keep the query efficient (as indexes etc. can't be used with a having clause easily).
SELECT
room_availability_rid
WHERE room_availability_date IN ('2011-02-13','2011-02-14','2011-02-15')
AND room_availability_number > 0
GROUP BY room_availability_rid
HAVING count(case room_availability_date when '2011-02-13' THEN 1 END) > 0
AND count(case room_availability_date when '2011-02-14' THEN 1 END) > 0
AND count(case room_availability_date when '2011-02-15' THEN 1 END) > 0
I think I can improve on a'r's answer:
SELECT
room_availability_rid, count(*) n
WHERE room_availability_date IN ('2011-02-13','2011-02-14','2011-02-15')
AND room_availability_number > 0
GROUP BY room_availability_rid
HAVING n=3
Edit: This of course assumes that there is only one table entry per room per day. Is this a valid assumption?
You can group by room ID, generate a list of dates available, and then see if all the dates you need are included.
This will give you a list of dates each room is available:
select `room_availability_rid`,group_concat(`room_ availability_date`) as `datelist`
from `table` where room_availability_number>0
group by `room_availability_rid`
Then we can add a having clause to get the rooms that are available on all of the dates we need:
select `room_availability_rid`,group_concat(`room_ availability_date`) as `datelist`
from `table` where room_availability_number>0
group by `room_availability_rid`
having find_in_set('2011-02-13',`datelist`) and
find_in_set('2011-02-14',`datelist`) and
find_in_set('2011-02-15',`datelist`)
This should work. Test it for me will ya? :)