Running count of distinct values in Access - ms-access

I have data stored as below in an MS Access database:
Date User
20090101 1001
20090101 1002
20090102 1001
20090103 1001
20090103 1003
I'm attempting to create a query which shows the daily running count of unique users. For example:
Date Daily Count Unique User Running Count
20090101 2 2
20090102 1 2
20090103 2 3
What's the best way to achieve this?

In most SQL implementations you could select using the aggregate function count(distinct user). But Access doesn't support that construct. I think the best you could do is to select the distinct values in a subquery and count them.
I was going to write a query but this link seems to do a good job.
HTH
Tom

Your query will look something like this...can't test it without the data though:
SELECT Date, Count(Date) As [Daily Count], Count(User) As [Unique User Running Count]
FROM TableName
GROUP BY Date

I did it! A simple solution is the best: no SQL coding needed.
In Access, Query Design,
Column 1 =
Field=Date
tablename=yourname
Total=Groupby
Column2 =
Field=Date
Table=yourname
Total=Count

Related

Jet SQL/MS Access - Query, count of tasks, sum of time, by user

I would really appreciate help in achieving the correct output, I want to understand how it works and self teach.
I have one table:
I would like to achieve the below results from one query:
user_name | task | CountOftask | SumOftime
U1 1 1 00:15
U2 1 1 00:25
U2 2 1 00:05
U3 2 1 00:20
U3 3 2 00:40
re: the table 'tasks':
The time field is date/time hh:nn.
The date field is irrelevant for the query at this stage - I want all historic data returned.
re: the query:
I would like to see a Count of task, SUM of time and Group by user_name & task, using one query with a sub select, instead of two separate queries.
Thanks for your time
Edit:
I can create this output, but I use two queries (Q1) to convert the time to integer, summing it. (Q2) using Q1 convert the integer back to time hh:mm.
Q1:
SELECT
user_name
, task
, Count(task) AS CountOftask
, Sum(CLng(24*60*CDate([time]))) AS time_mins
FROM tasks
GROUP BY user_name, task;
Q2:
SELECT
[301 SF count of task].user_name
, [301 SF count of task].task
, [301 SF count of task].CountOftask
, [time_mins]\60 & Format([time_mins] Mod 60,"\:00") AS Time_sum
FROM [301 SF count of task]
;
I would like to be able to do this in one query, any advice is appreciated.
Try with:
Select
user_name,
Max(task) As max_task,
Count(*) As task_count,
CDate(Sum([time])) As total_time
From
YourTable
Group By
user_name,
task
Edit - if time is text:
Sum(CDate([time])) As total_time
or forced to date value:
CDate(Sum(CDate([time]))) As total_time

MySQL: How to get TOP visited product for each user in a table?

I have a system with products. Everytime a user enters a product, I insert a record into my database.
I have a table with users and id_products, like this:
users id_product
____________________________
jondoe 2
george 9
jondoe 5
jondoe 2
george 9
george 9
george 2
I need a result (query) wich shows what is TOP visited product id for each user, so the result would be something like this:
jondoes most visited product is ID 2
georges most visitedproduct is ID 9
I was looking for the answer but I am not able to figure it out. Thanks a lot for your help, I appreciate it a lot.
Jan
This is a pain because it involves aggregation. One way to solve this uses a very complicated query. Another uses variables. A third method uses an aggregation trick that works under many circumstances:
select user,
substring_index(group_concat(id_product order by cnt desc), ',', 1) as mostCommonProduct
from (select user, id_product, count(*) as cnt
from t
group by user, id_product
) t
group by user;
One danger when using this method is that the intermediate result might be too long. You can set the group_concat_max_len system variable to get around that particular problem.

Subquery with max value in a big table SQL

I'm trying to make a query to get the date of last work experience of a person and also the date they left the company (in some cases that value is null because the person is still working on the company).
I have something like:
SELECT r.idcurriculum, r.startdate, r.lastdate FROM (
SELECT idcurriculum, max(startdate) as startdate
FROM workexperience
GROUP BY idcurriculum) as s
INNER JOIN workexperience r on (r.idcurriculum = s.idcurriculum)
The structure should come out something like this:
idcurriculum | startdate | lastdate
1234 | 2010-05-01| null
2532 | 2005-10-01| 2010-02-28
5234 | 2011-07-01| 2013-10-31
1025 | 2012-04-01| 2014-03-31
I tried running that query but I had to stop it because it was taking too long. The workexperience table weights aprox 20GB. I don't know if the query is wrong, I've only run it for 10 minutes.
Help will be much appreciated.
You might try rephrasing the query as:
select r.*
from workexperience we
where not exists (select 1
from workexperience we2
where we2.idcurriculum = we.idcurriculum and
we2.startdate > we.startdate
);
Important: for performance reasons you need a composite index on idcurriculum, startdate:
create index idx_workexperience_idcurriculum_startdate on workexperience(idcurriculum, strtdate)
The logic of the query is: "Get me all rows from workexperience where there is no row for the same idcurriculum that has a larger startdate". That is a fancy way of saying "get me the maximum".
With the group by, MySQL has to do an aggregation, which would typically involve sorting the data -- expensive on 20 Gbytes. With this method, it can look up the results using the index, which should be faster.
As an alternative to Gordon's answer you could also write the query as:
SELECT r.*
FROM work_experience we
LEFT JOIN work_experience we2
ON we2.idcurriculum = we.idcurriculum
AND we2.startdate > we.startdate
WHERE we2.idcurriculum IS NULL;
You can run into problems when there are multiple maximum start_dates in the group however.

Selecting most recent as part of group by (or other solution ...)

I've got a table where the columns that matter look like this:
username
source
description
My goal is to get the 10 most recent records where a user/source combination is unique. From the following data:
1 katie facebook loved it!
2 katie facebook it could have been better.
3 tom twitter less then 140
4 katie twitter Wowzers!
The query should return records 2,3 and 4 (assume higher IDs are more recent - the actual table uses a timestamp column).
My current solution 'works' but requires 1 select to generate the 10 records, then 1 select to get the proper description per row (so 11 selects to generate 10 records) ... I have to imagine there's a better way to go. That solution is:
SELECT max(id) as MAX_ID, username, source, topic
FROM events
GROUP BY source, username
ORDER BY MAX_ID desc;
It returns the proper ids, but the wrong descriptions so I can then select the proper descriptions by the record ID.
Untested, but you should be able to handle this with a join:
SELECT
fullEvent.id,
fullEvent.username,
fullEvent.source,
fullEvent.topic
FROM
events fullEvent JOIN
(
SELECT max(id) as MAX_ID, username, source
FROM events
GROUP BY source, username
) maxEvent ON maxEvent.MAX_ID = fullEvent.id
ORDER BY fullEvent.id desc;

Complex MySQL COUNT query

Evening folks,
I have a complex MySQL COUNT query I am trying to perform and am looking for the best way to do it.
In our system, we have References. Each Reference can have many (or no) Income Sources, each of which can be validated or not (status). We have a Reference table and an Income table - each row in the Income table points back to Reference with reference_id
On our 'Awaiting' page (the screen that shows each Income that is yet to be validated), we show it grouped by Reference. So you may, for example, see Mr John Smith has 3 Income Sources.
We want it to show something like "2 of 3 Validated" beside each row
My problem is writing the query that figures this out!
What I have been trying to do is this, using a combination of PHP and MySQL to bridge the gap where SQL (or my knowledge) falls short:
First, select a COUNT of the number of incomes associated with each reference:
SELECT `reference_id`, COUNT(status) AS status_count
FROM (`income`)
WHERE `income`.`status` = 0
GROUP BY `reference_id`
Next, having used PHP to generate a WHERE IN clause, proceed to COUNT the number of confirmed references from these:
SELECT `reference_id`, COUNT(status) AS status_count
FROM (`income`)
WHERE `reference_id` IN ('8469', '78969', '126613', ..... etc
AND status = 1
GROUP BY `reference_id`
However this doesn't work. It returns 0 rows.
Any way to achieve what I'm after?
Thanks!
In MySQL, you can SUM() on a boolean expression to get a count of the rows where that expression is true. You can do this because MySQL treats true as the integer 1 and false as the integer 0.
SELECT `reference_id`,
SUM(`status` = 1) AS `validated_count`,
COUNT(*) AS `total_count`
FROM `income`
GROUP BY `reference_id`