MS Access Query - Count using most recent inquiries - sql

I am still new to this Access and am not sure how to do this. I have this prospective customer table:
my table and the expected result:
Or here is the data, not sure if it will show correctly:
ID Dates Status
1 12-Sep-15 Follow up
1 2-Jan-15 Request
1 15-Apr-14 Letter
2 1-Sep-15 Request
2 1-Apr-15 Letter
3 12-Dec-15 Follow up
3 11-Sep-14 Request
3 12-Mar-14 Letter
4 14-Jan-16 Letter
4 12-Dec-15 Email
5 12-Jan-16 Letter
5 1 Des 2015 Email
And the result would be like this:
Follow up 2
Request 1
Letter 2
I first tried this SQL:
SELECT id, status, Max(dates) AS TEST
FROM Sample
GROUP BY id, status;
which still would give me the original table. I was hoping it would return the id and status for most recent dates.
Any help would be deeply appreciated. Thank you very much !!

If you want id and status for the latest date, then you need to use a subselect to get the max dates by id and join your table on it by id and date:
SELECT s.id, s.status, t.maxdate
FROM status as s
INNER JOIN
(SELECT id, Max(dates) AS maxdate
FROM Sample
GROUP BY id) as t ON t.id=s.id and t.maxdate=s.dates

Related

Postgres, groupBy and count for table and relations at the same time

I have a table called 'users' that has the following structure:
id (PK)
campaign_id
createdAt
1
123
2022-07-14T10:30:01.967Z
2
1234
2022-07-14T10:30:01.967Z
3
123
2022-07-14T10:30:01.967Z
4
123
2022-07-14T10:30:01.967Z
At the same time I have a table that tracks clicks per user:
id (PK)
user_id(FK)
createdAt
1
1
2022-07-14T10:30:01.967Z
2
2
2022-07-14T10:30:01.967Z
3
2
2022-07-14T10:30:01.967Z
4
2
2022-07-14T10:30:01.967Z
Both of these table are up to millions of records... I need the most efficient query to group the data per campaign_id.
The result I am looking for would look like this:
campaign_id
total_users
total_clicks
123
3
1
1234
1
3
I unfortunately have no idea how to achieve this while minding performance and most important of it all I need to use WHERE or HAVING to limit the query in a certain time range by createdAt
Note, PostgreSQL is not my forte, nor is SQL. But, I'm learning spending some time on your question. Have a go with INNER JOIN after two seperate SELECT() statements:
SELECT * FROM
(
SELECT campaign_id, COUNT (t1."id(PK)") total_users FROM t1 GROUP BY campaign_id
) tbl1
INNER JOIN
(
SELECT campaign_id, COUNT (t2."user_id(FK)") total_clicks FROM t2 INNER JOIN t1 ON t1."id(PK)" = t2."user_id(FK)" GROUP BY campaign_id
) tbl2
USING(campaign_id)
See an online fiddle. I believe this is now also ready for a WHERE clause in both SELECT statements to filter by "createdAt". I'm pretty sure someone else will come up with something better.
Good luck.
Hope this will help you.
select u.campaign_id,
count(distinct u.id) users_count,
count(c.user_id) clicks_count
from
users u left join clicks c on u.id=c.user_id
group by 1;
See here query output

Find status from separate fact table

This is in snowflake, but I can figure out any other syntax that is similar.
I have a table of employees and the date they received a paycheck
EMP_ID
Check_dt
1
10-7-2021
2
9-28-2021
1
3-1-2021
And a table that has employee history for full/part time status changes, and the date the change was made effective
EMP_ID
Status
Effective Date
1
F
1/1/20201
2
P
1/1/2021
1
P
6/1/2021
(In this example, employee 1 changed from full to part time halfway through the year)
I want to get the status (F/P) of the employee at the time they received their paycheck.
The output I want is:
EMP_ID
Check_dt
Status
1
10-7-2021
P
2
9-28-2021
P
1
3-1-2021
F
Thanks in advance!
Try this
Select empid, case when t1.chkdate<= (Select
max(effect_date) from
table2 where empid=t1.empid) then t1.status) end as
status
From table1 t1

How do I count how many emails each customer has received when there are multiple emails to count?

I am looking to count the number of emails each customer has received however am having trouble as there is more than one customer in the table that needs counting meaning a simple where clause isn't enough.
Here is an example of the Data:
CustomerID
EmailName
1
EmailA
1
EmailB
2
EmailA
2
EmailB
2
EmailC
3
EmailA
3
EmailB
I am able to count for a specific customer by using a where clause:
WHERE CustomerID = "1"
Which will return:
CustomerID
NumberOfEmailsSent
1
2
The issue I am having is I would like to get the following result:
CustomerID
NumberOfEmailsSent
1
2
2
3
3
2
The data set I am working with has thousands of email addresses so querying each email address separately is an unrealistic solution.
That is what GROUP BY is for.
SELECT CustomerID, COUNT(EmailName)
FROM YourTable
GROUP BY CustomerID
I think that you just need a GROUP BY clause:
SELECT CustomerID, COUNT(EmailName) as 'NumberOfEmailsSent'
FROM tbl
GROUP BY CustomerID
Output check here on DB<>FIDDLE

SQL - Removing Duplicate without 'hard' coding?

Heres my scenario.
I have a table with 3 rows I want to return within a stored procedure, rows are email, name and id. id must = 3 or 4 and email must only be per user as some have multiple entries.
I have a Select statement as follows
SELECT
DISTINCT email,
name,
id
from table
where
id = 3
or id = 4
Ok fairly simple but there are some users whose have entries that are both 3 and 4 so they appear twice, if they appear twice I want only those with ids of 4 remaining. I'll give another example below as its hard to explain.
Table -
Email Name Id
jimmy#domain.com jimmy 4
brian#domain.com brian 4
kevin#domain.com kevin 3
jimmy#domain.com jimmy 3
So in the above scenario I would want to ignore the jimmy with the id of 3, any way of doing this without hard coding?
Thanks
SELECT
email,
name,
max(id)
from table
where
id in( 3, 4 )
group by email, name
Is this what you want to achieve?
SELECT Email, Name, MAX(Id) FROM Table WHERE Id IN (3, 4) GROUP BY Email;
Sometimes using Having Count(*) > 1 may be useful to find duplicated records.
select * from table group by Email having count(*) > 1
or
select * from table group by Email having count(*) > 1 and id > 3.
The solution provided before with the select MAX(ID) from table sounds good for this case.
This maybe an alternative solution.
What RDMS are you using? This will return only one "Jimmy", using RANK():
SELECT A.email, A.name,A.id
FROM SO_Table A
INNER JOIN(
SELECT
email, name,id,RANK() OVER (Partition BY name ORDER BY ID DESC) AS COUNTER
FROM SO_Table B
) X ON X.ID = A.ID AND X.NAME = A.NAME
WHERE X.COUNTER = 1
Returns:
email name id
------------------------------
jimmy#domain.com jimmy 4
brian#domain.com brian 4
kevin#domain.com kevin 3

Using count I'm only getting one row back

I have a table like the following
User Item
A 1
A 1
A 1
B 1
B 2
C 2
C 2
A 2
I'm trying to run a query so I can get an output such as
User Item Count
A 1 3
B 1 1
B 2 1
A 2 1
C 2 2
I've tried the following query, however I'm not getting the output right.
select f.item,f.uid, COUNT(f.uid) as count
from fresh f,
product p
where f.locationid = p.iid
group by f.locationid, f.uid
order by f.uid desc;
Can anyone point out how I write a query to get the required output? I could write it up in python / ruby but I think it'll take a lot longer to run! :(
Select user, Item, count(*) Count From tablename
Group by User, Item
Order by Item
SELECT user, item, count(*) FROM fresh GROUP BY user, item
Why are you joining to the product table, when it is not used in the results?
That is likely cause of the issue, since it is an inner join, when there isn't a match, there will be no result, so you'll lose data, try just:
select
item,
uid,
COUNT(*) as count
from
fresh
group by
locationid,
uid
order by
uid desc
;