MYSQL Calculate Conversion Rate - mysql

I could manage to return the correct Conversion Rate with this query:
SELECT
date(ordertime),
(count(*) / (
SELECT
sum(uniquevisits)
FROM
s_statistics_visitors
WHERE
datum = '2020-11-25') * 100) AS 'CONVERSION RATE'
FROM
s_order
WHERE
date(ordertime) = '2020-11-25'
AND subshopID = 1
GROUP BY
date(ordertime);
But it only returns the CR for one specific date. It wont work with the between keyword.
The subquery returns more then one result, if I delete the where condition in the subquery.
Schema for s_statistics: id, shopID, datum, uniquevisits, devicetype
Schema for s_order: id, ordernumber, ordertime, shopID
Since s_statistics saves values for each devicetype I have to sum uniquevisits per day. But the group by date(ordertime) at the end of my query does not affect the subquery.
-original post-
I want to calculate the conversion rate for an onlineshop.
The data is held in two tables.
Schema1 statistics: id / shopID / datum(yyyy-mm-dd) / uniquevisits / devicetype
Schema2 order: id / ordernumber / ordertime (YYYY-MM-DD HH-MM-SS)
Upon my knowledge the conversionrate calculates like:
(unique visits per day / 1000) * orders per day
I tried something like this:
SELECT
((count(ordernumber) / 1000) * (select sum(s_statistics_visitors.uniquevisits)
FROM s_statistics_visitors GROUP BY* datum))
FROM s_order where subshopID= '1'
GROUP BY date_format(ordertime, '%d%m%y')
ORDER BY date_format(ordertime, '%d%m%y')
I know that my query wont work - since there is no join - but I believe it might be the right approach. I could you join on the the date.
The problem:
the dateformat in the table: s_statistics_visitors is YYYY-MM-DD
and in order: YYYY-MM-DD HH-MM-SS

You seem to want something like this:
SELECT sv.datum, sv.shopId, count(*) as num_orders,
(count(*) / 1000) / sv.uniquevisits)
FROM s_order o JOIN
s_statistics_visitors sv
ON sv.datum = DATE(o.ordertime) AND
sv.shopId = o.shopId
GROUP BY sv.datum, sv.shopId, sv.uniqevisits ;
Note: This assumes that shopId is in both tables -- which makes sense for how you have described the problem. If not, you can adjust the shop id logic.

Related

Who to the number of users who have had one transaction per day?

Here is my query:
select count(1) from
(select count(1) num, user_id from pos_transactions pt
where date(created_at) <= '2020-6-21'
group by user_id
having num = 1) x
It gives me the number of users who have had 1 transaction until 2020-6-21. Now I want to group it also per date(created_at). I mean, I want to get a list of dates (such as 2020-6-21, 2020-6-22 etc ..) plus the number of users who have had 1 transaction in that date (day).
Any idea how can I do that?
EDIT: The result of query above is correct, the issue is, it's manually now. I mean, I have to increase 2020-6-21 by hand. I want to make it automatically. In other words, I want a list of all dates (from 2020-6-21 til now) contains the number of users who have had 1 transaction until that date.
If you want the number of users who had one transaction on each day, then you need to aggregate by the date as well:
select dte, count(*)
from (select date(created_at) as dte, user_id
from pos_transactions pt
where date(created_at) <= '2020-6-21'
group by dte, user_id
having count(*) = 1
) du
group by dte;

Calculate percentage by group based on values in one column

Apologies for the basic question, I could not find the answer after searching.
A simple table with 2 columns car_type and event.
Each time a customer inquires about a car, a record is put into the table and event = "inquire". If that car type is bought, a record of event = "bought" is put in.
How would I calculate which car type is the most successful, based off # bought / # inquired? Grouped by car type of course.
I've tried
select car_type,
((select count(*) from TABLE where event = "bought" ) /
(select count(*) from alerts where event = "inquire") * 100.0) as percentage
from TABLE
group by car_type;
but this hasn't worked.
Thank you in advance!
You could use conditional aggregation:
select car,
(sum( event = 'bought') /
sum( event = 'inquire' )
) as bought_inquire_ratio
from t
group by car;
If you simply want the bought ratio overall you can use:
select car,
avg( event = 'bought' )
from t
group by car;
You can sum the different event types for each car (most easily in a subquery) and then divide the results to get the percentage, ordering by that value descending and taking only the top value:
SELECT car_type, 100.0 * bought / inquiries AS percentage
FROM (
SELECT car_type,
SUM(event = 'bought') AS bought,
SUM(event = 'inquire') AS inquiries
FROM alerts
GROUP BY car_type
) c
ORDER BY percentage DESC
LIMIT 1

How to combine two sql expressions into one?

I have the following issue:
It is necessary to write a query that will output 'item_id', 'price_in_byr'.
'price_in_byr' is calculated as the 'price' of the items table multiplied by the currency rate at the maximum date of the rate from the table rates.
See Schema
I apologize for my English, I'll try to explain by example:
Goods with item_id = 5 costs 20 euros, in the rates table the maximum date for the euro is January 12, at that date the exchange rate was 25. Total our 'price_in_byr' is 25 * 20 = 500
My solution with temp table:
CREATE TABLE tempRate SELECT currency, MAX(rate) AS maxRate FROM rates GROUP
BY currency;
SELECT items.item_id,(ifnull(tempRate.maxRate,1) * items.price) AS price_in_byr
FROM items
LEFT JOIN tempRate ON items.currency = tempRate.currency;
Tell me please, how can I do it in one query?
You can just use a subquery:
SELECT
items.item_id,(ifnull(tempRate.maxRate,1) * items.price) AS price_in_byr
FROM
items
LEFT JOIN
(
SELECT
currency, MAX(rate) AS maxRate
FROM
rates
GROUP BY
currency
) AS tempRate
ON items.currency = tempRate.currency;
In practice, you substitute "tempRate" by (definition of tempRate) AS tempRate.
You can see an example at dbfiddle here
If you actually want the * most_recent_rate*, you'd do something completely different; insert a subquery to compute it. This subquery looks for all rates of the given currency, sorts them by their exchange_ts (meaning timestamp) in descending order, and just picks to top 1:
SELECT
items.item_id,(ifnull(
(
SELECT
rate AS most_recent_rate
FROM
rates
WHERE
rates.currency = items.currency
ORDER BY
exchange_ts DESC
LIMIT 1
)
, 1) * items.price) AS price_in_byr
FROM
items ;
dbfiddle here
You can make your tempRate query into a subquery:
SELECT
items.item_id,
(ifnull(tempRate.maxRate,1) * items.price) AS price_in_byr
FROM
items
LEFT JOIN (
SELECT currency, MAX(rate) AS maxRate
FROM rates
GROUP BY currency
) as tempRate ON items.currency = tempRate.currency;
I am not sure if mysql supports this level of subquery but see if it works:
select I.item_id, I.price * CR.rt
from
items as I,
(
select r.currency cy, r.rate rt
from
rates as r, (select currency, max(date) max_date from rates group by currency) as R_MAXDATES
where
r.currency = R_MAXDATES.currency
and r.date = R_MAXDATES.max_date;
) As CR
where
I.currency = CR.cy

Counting users between two dates

I have a table that has just two fields - a date field and customer_id. I am looking to count the number of customer ids from each date field to current date. My query below is timing out - seems very inefficient. Is there a better way to do this?
select
t.base_date,
( select
count(distinct customer_id)
from user_base as ub
where ub.base_date >= t.base_date
and ub.base_date <= current_date
) as cts
from user_base as t
Try if this gives you same results not tested but seems the way you extracted data was not the right way of doing:
select base_date, count(distinct customer_id) as cts
from user_base
where base_date between base_date AND current_date

SQL Work out the average time difference between total rows

I've searched around SO and can't seem to find a question with an answer that works fine for me. I have a table with almost 2 million rows in, and each row has a MySQL Date formatted field.
I'd like to work out (in seconds) how often a row was inserted, so work out the average difference between the dates of all the rows with a SQL query.
Any ideas?
-- EDIT --
Here's what my table looks like
id, name, date (datetime), age, gender
If you want to know how often (on average) a row was inserted, I don't think you need to calculate all the differences. You only need to sum up the differences between adjacent rows (adjacent based on the timestamp) and divide the result by the number of the summands.
The formula
((T1-T0) + (T2-T1) + … + (TN-TN-1)) / N
can obviously be simplified to merely
(TN-T0) / N
So, the query would be something like this:
SELECT TIMESTAMPDIFF(SECOND, MIN(date), MAX(date)) / (COUNT(*) - 1)
FROM atable
Make sure the number of rows is more than 1, or you'll get the Division By Zero error. Still, if you like, you can prevent the error with a simple trick:
SELECT
IFNULL(TIMESTAMPDIFF(SECOND, MIN(date), MAX(date)) / NULLIF(COUNT(*) - 1, 0), 0)
FROM atable
Now you can safely run the query against a table with a single row.
Give this a shot:
select AVG(theDelay) from (
select TIMESTAMPDIFF(SECOND,a.date, b.date) as theDelay
from myTable a
join myTable b on b.date = (select MIN(x.date)
from myTable x
where x.date > a.date)
) p
The inner query joins each row with the next row (by date) and returns the number of seconds between them. That query is then encapsulated and is queried for the average number of seconds.
EDIT: If your ID column is auto-incrementing and they are in date order, you can speed it up a bit by joining to the next ID row rather than the MIN next date.
select AVG(theDelay) from (
select TIMESTAMPDIFF(SECOND,a.date, b.date) as theDelay
from myTable a
join myTable b on b.date = (select MIN(x.id)
from myTable x
where x.id > a.id)
) p
EDIT2: As brilliantly commented by Mikael Eriksson, you may be able to just do:
select (TIMESTAMPDIFF(SECOND,(MAX(date),MIN(date)) / COUNT(*)) from myTable
There's a lot you can do with this to eliminate off-peak hours or big spans without a new record, using the join syntax in my first example.
Try this:
select avg(diff) as AverageSecondsBetweenDates
from (
select TIMESTAMPDIFF(SECOND, t1.MyDate, min(t2.MyDate)) as diff
from MyTable t1
inner join MyTable t2 on t2.MyDate > t1.MyDate
group by t1.MyDate
) a