I have a table that shows , for each date, a list of customer ids - shows customers who were active on any particular day. So each date can include ids that are also present in another date.
bdate customer_id
2012-01-12 111
2012-01-13 222
2012-01-13 333
2012-01-14 111
2012-01-14 333
2012-01-14 666
2012-01-14 777
I am looking to write a query which calculates the total number of unique ids between two dates - the starting date is the row date and the ending date is a particular date in the future.
My query looks like this:
select
bdate,
count(distinct customer_id) as cts
from users
where bdate between bdate and current_date
group by 1
order by 1
But this produces a count of unique users for each date like this:
bdate customer_id
2012-01-12 1
2012-01-13 2
2012-01-14 4
my desired result is ( for a count of users between starting row date and 2012-01-14 )
bdate customer_id
2012-01-12 5 - includes (111,222,333,666,777)
2012-01-13 5 - includes (222,333,111,666,777)
2012-01-14 4 - includes (111,333,666,777)
Like #Strawberry said, you can make a join like this:
select
t1.bdate,
count(distinct t2.customer_id) as cts
from users t1
join users t2 on t2.bdate >= t1.bdate
where t1.bdate between t1.bdate and current_date
group by t1.bdate
order by t1.bdate
join t2 can get you all the users between particular day and current_date, then count t2's customer_id, that's it.
SqlFiddle Demo Here
Related
I have the following table called employees:
employee
name
101
John
102
Alexandra
103
Ruth
And the table called records:
employee
assistance
101
2022-02-01
101
2022-02-02
101
2022-02-07
Let's suppose that I want to display the employee number, name and the days of the month in which there were absences between 2022-02-01 and 2022-02-07 (taking into account that days 05 and 06 are weekends). In that case, the result would be the following:
employee
name
absence
101
John
4,5
How do I get that result?
So far I have developed a query where the days of the month in which there are attendances are displayed. Said query is as follows:
SELECT e.employee,
e.name,
r.assistance AS assistance,
OF employees and
JOIN LEFT(SELECT employee, GROUP_CONCAT(DIFFERENT EXTRACT(DAY SINCE assistance)
ORDER BY STATEMENT(DAY FROM assistance)) AS assistance FROM records
WHERE assistance BETWEEN '2022-02-01' AND '2022-02-07' GROUP BY employee) r ON e.employee = employee
WHERE (r.no_employee IS NOT NULL) ORDER BY name ASC
I would like to know how to implement the days in which there were absences and not consider the weekends. I've done several tests but I'm still stuck. I'm working with MariaDB 10.4.11
You use a recursive common table expression (requires mariadb 10.2+ or mysql 8) to get the list of dates in the date range, and join against that:
with recursive date_range as (
select '2021-12-01' dt
union all
select dt + interval 1 day from date_range where dt < '2021-12-07'
)
select employee.employee, group_concat(day(date_range.dt) order by date_range.dt) faults
from date_range
cross join employee
left join records on records.employee=employee.employee and records.assistance=date_range.dt
where weekday(date_range.dt) < 5 and records.employee is null
group by employee.employee
fiddle
If you are just looking for one employee, add that as a where condition.
I have a table that looks like this
id
date registered
date cancelled
1
2021-01-01
2021-03-02
2
2021-01-05
2021-01-21
3
2021-02-04
2021-02-25
4
2021-02-16
2021-03-26
How do I generate a query in mysql that will give me counts of cancelled and registered for each month.
I can do it for just one of the dates but don't know how to combine for both dates.
For eg for a single date I would do this.
SELECT date_format(`users`.`dateregistered`,_utf8'%Y-%m') AS `DateREegistered`, count(0) AS `Registration Count`
FROM `users`
GROUP BY date_format(`users`.`dateregistered`,_utf8'%Y-%m')
But I want something like this
Date
Registered Count
Cancelled Count
2021-01
2
1
2021-02
2
1
2021-03
0
2
Please let me know if you have any ideas.
You can join the distinct months appearing in date registered and date registered to the table and use conditional aggregation:
SELECT t.Date,
SUM(t.Date = date_format(dateregistered, '%Y-%m')) `Registered Count`,
SUM(t.Date = date_format(datecancelled, '%Y-%m')) `Cancelled Count`
FROM (
SELECT date_format(dateregistered, '%Y-%m') Date FROM users
UNION
SELECT date_format(datecancelled, '%Y-%m') FROM users
) t INNER JOIN users u
ON t.Date IN (date_format(dateregistered, '%Y-%m'), date_format(datecancelled, '%Y-%m'))
GROUP BY t.Date
See the demo.
Results:
Date
Registered Count
Cancelled Count
2021-01
2
1
2021-02
2
1
2021-03
0
2
I have a cron script that writes the total number of active users to a table every day. I'm trying to now generate a simple report that would show the "high water mark" for each month. Because some accounts expire during the month it's possible the highest number may NOT be at the end of the month.
Here's a sample of my table structure
tblUserLog
-----------
record_id INT(11) // PRIMARY KEY
run_date DATE // DATE RUN
ttl_count INT(11) // TOTAL FOR DAY
Sample data:
record_id run_date ttl_count
1 2013-06-01 500
2 2013-06-10 510
3 2013-06-20 520
4 2013-06-30 515
5 2013-07-01 525
6 2013-07-10 530
7 2013-07-20 540
8 2013-07-31 550
9 2013-08-01 560
What I would like returned is:
record_id run_date ttl_count
3 2013-06-20 520
8 2013-07-31 550
9 2013-08-01 560
I've tried two queries that are close...
// This will give me the total for the first of the month
SELECT s.record_id, s.run_date, s.ttl_count
FROM tblStatsIndividual s
JOIN (
SELECT record_id
FROM tblStatsIndividual
GROUP BY DATE_FORMAT(run_date, '%Y %m')
HAVING MAX(ttl_count)
) s2
ON s2.record_id = s.record_id
ORDER BY run_date DESC
This returns the total for the first of each month, along with the record_id and correct date for the total.
Tried this...
SELECT record_id,max(run_date), max(ttl)
FROM (
SELECT record_id,run_date, max(ttl_count) AS ttl
FROM tblStatsIndividual
GROUP BY DATE_FORMAT(run_date, '%Y %m')
) a
GROUP BY DATE_FORMAT(run_date, '%Y %m')
ORDER BY run_date DESC
This one appears to get the correct "high water mark" but it's not returning the record_id, or the run_date for the row that IS the high water mark.
How do you get the record_id and the run_date for the highest total?
Something like
Select detail.Record_ID, detail.Run_Date, detail.ttl_Count
From tblStatsIndividual detail
Inner Join
(Select Year(run_date) as Year, Month(Run_date) as Month, Max(ttl_count) as ttl
From tblStatsIndividual
Group By Year(run_date), Month(Run_date)) maximums
On maximums.Year = Year(detail.Run_date) and maximums.Month = Month(detail.Run_date)
and maximums.ttl = detail.ttl_count
Should do it. NB based on your requirement if you had two records in the same month with the same (and highest in the month) ttl_count, they would both be returned.
Based on the help from #Tony Hopkinson, This query gets me the info. The one caveat is it shows the ID and date for the first occurrence of the MAX total, so if the total is the same three days in a row on a month, the first day's ID is returned. For my purpose, the last ID would be more ideal, but I can live with this:
SELECT s.Record_ID, s.Run_Date, s.ttl_Count
FROM tblStatsIndividual s
INNER JOIN (
SELECT YEAR(run_date) AS yr, MONTH(run_date) AS mon, MAX(ttl_count) AS ttl
FROM tblStatsIndividual
GROUP BY DATE_FORMAT(run_date, '%Y %m')
) maximums
ON maximums.yr = YEAR(s.run_date)
AND maximums.mon = MONTH(s.run_date)
AND maximums.ttl = s.ttl_Count
GROUP BY ttl_count
ORDER BY run_date DESC
I have a table - user_tracking - which stores the user_id, purchase sku, and event time_created. Each time a user returns to purchase the original user_id is referenced with a new timestamp:
User_ID Sku Time_Created
1 1234 2012-10-01 01:00:00
2 2345 2012-10-02 02:00:00
3 6789 2012-10-02 01:00:00
2 5432 2012-10-04 04:00:00
I want to measure the return customer usage, but only for customers that have returned within 7-60 days of initial purchase. Currently my query looks something like:
SELECT
total_purchases.user_id as user_1_id,
total_purchases.time_created as time_1_created,
total_purchases.total_purchases as total_original_purchases,
total_return.user_id as user_2_id,
total_return.time_created as time_2_created,
total_return.total_return_purchases as total_return_purchases
FROM (SELECT
user_tracking.user_id as user_id,
user_tracking.time_created as time_created,
COUNT(DISTINCT user_tracking.sku) as total_purchases
FROM user_tracking
WHERE user_tracking.time_created BETWEEN "2012-10-01 00:00:00"
AND "2012-10-15 00:00:00") AS total_purchases
LEFT JOIN (SELECT
user_tracking.user_id as user_id,
user_tracking.time_created as time_created,
COUNT(DISTINCT user_tracking.sku) as total_return_purchases
FROM user_tracking
WHERE user_tracking.time_created BETWEEN "2012-10-01 00:00:00"
and "2012-12-15 00:00:00") AS total_return
ON total_purchases.user_id = total_return.user_id
How can I ensure I'm only measuring purchases within 7-60 days with the original user?
You can use interval
AND datecolumn BETWEEN (datecolumn, INTERVAL 7 DAYS) AND (datecolumn, INTERVAL 60 DAYS)
I have the following table created by a join and some conditionals:
product_id date
11111 2012-06-05
11111 2012-05-01
22222 2011-05-01
22222 2011-07-02
33333 2011-01-01
I am trying to get the rows such that I have a result set with the latest date per product:
GOAL
product_id date
11111 2012-06-05
22222 2011-07-02
33333 2011-01-01
I could extract the data as is and do a manual sort, but I'd rather not. I cannot seem to find a way to do a SELECT MAX() without returning only a single row, and I'd rather not run a query for each product id.
The table is generated by this query:
SELECT item_id, sales_price, item, description, transaction_date
FROM db.invoice_line AS t1 INNER JOIN db.invoices AS t2
ON t1.invoice_id = t2.id_invoices WHERE item IS NOT NULL
AND item_id != '800001E9-1325703142' AND item_id != '800002C3-1326830147'
AND invoice_id IN
(SELECT id_invoices FROM db.invoices
WHERE customer_id = '[variable customer id]'
AND transaction_date >= DATE_SUB(NOW(), INTERVAL 360 DAY));
I use a join to 'add' the date column. After that, I disregard useless items, and select from invoices from a particular customer from a year ago to date.
Thanks for any guidance.
Dane
Looks like a group by would fit the bill:
select product_id
, max(date)
from YourTable
group by
product_id