ACCESS - Select rows on first occurrence of each unique value - ms-access

I got an ACCESS database related issue on which I already spend too much time without getting any hope to find a solution by myself
Let's imagine I got 3 tables like this
PROJECT_TABLE
+------------+--------------+
| PROJECT_ID | Project_Date |
+------------+--------------+
| Project01 | 01/01/2022 |
+------------+--------------+
| Project02 | 16/02/2020 |
+------------+--------------+
| Project03 | 19/03/2021 |
+------------+--------------+
| Project04 | 01/01/2022 |
+------------+--------------+
ACTIVITY_TABLE
+-------------+------------+
| ACTIVITY_ID | PROJECT_ID |
+-------------+------------+
| Activity01 | Project01 |
+-------------+------------+
| Activity02 | Project02 |
+-------------+------------+
| Activity03 | Project01 |
+-------------+------------+
| Activity04 | Project03 |
+-------------+------------+
| Activity05 | Project04 |
+-------------+------------+
| Activity06 | Project01 |
+-------------+------------+
| Activity07 | Project04 |
+-------------+------------+
| Activity08 | Project03 |
+-------------+------------+
ITEMS_TABLE
+---------+-------------+
| ITEM_ID | ACTIVITY_ID |
+---------+-------------+
| Item01 | Activity01 |
+---------+-------------+
| Item02 | Activity06 |
+---------+-------------+
| Item03 | Activity03 |
+---------+-------------+
| Item01 | Activity05 |
+---------+-------------+
| Item03 | Activity07 |
+---------+-------------+
| Item04 | Activity02 |
+---------+-------------+
| Item02 | Activity04 |
+---------+-------------+
| Item01 | Activity08 |
+---------+-------------+
Consolidated extract of last done for each activity that I need to get will look like this
+---------+-------------+------------+--------------+
| ITEM_ID | ACTIVITY_ID | PROJECT_ID | Project_Date |
+---------+-------------+------------+--------------+
| Item01 | Activity01 | Project01 | 01/01/2022 |
| | or | or | |
| | Activity05 | Project04 | |
+---------+-------------+------------+--------------+
| Item02 | Activity06 | Project01 | 01/01/2022 |
+---------+-------------+------------+--------------+
| Item03 | Activity03 | Project01 | 01/01/2022 |
| | or | or | |
| | Activity07 | Project04 | |
+---------+-------------+------------+--------------+
| Item04 | Activity02 | Project02 | 16/02/2020 |
+---------+-------------+------------+--------------+
The problem will be the or statement in this table, I need to get any of the two possible data.
At this moment I can get this
+---------+------------------+
| ITEM_ID | MaxDatePerformed |
+---------+------------------+
| Item01 | 01/01/2022 |
+---------+------------------+
| Item02 | 01/01/2022 |
+---------+------------------+
| Item03 | 01/01/2022 |
+---------+------------------+
| Item04 | 16/02/2020 |
+---------+------------------+
With the following query
SELECT ITEM_ID
,Max(Project_Date) AS MaxDatePerformed
FROM (
ITEMS_TABLE INNER JOIN (
ACTIVITY_TABLE INNER JOIN PROJECT_TABLE ON ACTIVITY_TABLE.PROJECT_ID = PROJECT_TABLE.PROJECT_ID
) ON ITEMS_TABLE.ACTIVITY_ID = ACTIVITY_TABLE.ACTIVITY_ID
) AS [ACTIVITY_DATE_INFO]
GROUP BY [ACTIVITY_DATE_INFO].ITEM_ID
But when I try to add ",ACTIVITY_ID" to this query I get "Your query doesn't include ACTIVITY_ID as aggregate function"
I know that a solution is existing for MySQL (MySQL Select rows on first occurrence of each unique value) but I can't find any for ACCESS, it seems that this "cheat" doesn't exist.

Consider:
Query1:
SELECT Items_Table.Item_ID, Activity_Table.Activity_ID, Project_Table.Project_ID, Project_Table.Project_Date
FROM Project_Table
RIGHT JOIN (Items_Table RIGHT JOIN Activity_Table ON Items_Table.Activity_ID = Activity_Table.Activity_ID)
ON Project_Table.Project_ID = Activity_Table.Project_ID;
Query2:
SELECT Item_ID, Activity_ID, Project_ID, Project_Date
FROM Query1 WHERE Activity_ID IN
(SELECT TOP 1 Activity_ID FROM Query1 AS Dupe
WHERE Dupe.Item_ID = Query1.Item_ID
ORDER BY Dupe.Project_Date DESC, Dupe.Activity_ID)
ORDER BY Item_ID;
Then try modification Dupe.Activity_ID DESC and see what happens.
For more info review http://allenbrowne.com/subquery-01.html

Related

MySQL Join one table to other two tables

I have a MySQL database including following tables that used to maintain transactions of some documents.
tbl_documents Table
+----+---------+------+---------+
| id | file_no | name | subject |
+----+---------+------+---------+
| 1 | A/10 | F1 | a |
| 2 | A/11 | F2 | b |
| 3 | A/12 | F3 | c |
| 4 | A/13 | F4 | d |
+----+---------+------+---------+
tbl_requests
+----+-------------+----------------+---------------+
| id | document_id | requested_date | approved_date |
+----+-------------+----------------+---------------+
| 1 | 1 | 2019-12-01 | 2019-12-02 |
| 2 | 2 | 2019-12-08 | 2019-12-08 |
+----+-------------+----------------+---------------+
tbl_issues
+----+-------------+------------+
| id | document_id | issue_date |
+----+-------------+------------+
| 1 | 1 | 2019-12-05 |
| 2 | 2 | 2019-12-10 |
+----+-------------+------------+
I want to get the following / Desired output by joining above three tables.
Desired Output
+---------+------+---------+----------------+---------------+------------+
| file_no | name | subject | requested_date | approved_date | issue_date |
+---------+------+---------+----------------+---------------+------------+
| A/10 | F1 | a | 2019-12-01 | 2019-12-02 | 2019-12-05 |
| A/11 | F2 | b | 2019-12-08 | 2019-12-08 | 2019-12-10 |
+---------+------+---------+----------------+---------------+------------+
To do that, I used the following query
select tbl_documents.file_no, tbl_documents.name, tbl_documents.subject, requested_date, approved_date, tbl_issues.issue_date
from tbl_documents
right join tbl_requests on tbl_requests.document_id=tbl_documents.id
right join tbl_issues on tbl_issues.document_id=tbl_documents.id
But didn't get the expected output. Can anyone help ?
Just use inner joins, as in:
select
d.file_no,
d.name,
d.subject,
r.requested_date,
r.approved_date,
i.issue_date
from tbl_documents d
join tbl_requests r on r.document_id = d.id
join tbl_issues i on i.document_id = d.id

MYSQL Max Value of status

I have the following tables that records the details of letters vs actions, taken for them.
letter table
+-----------+-------------+
| letter_id | description |
+-----------+-------------+
| 1 | A |
| 2 | B |
| 3 | C |
| 4 | D |
+-----------+-------------+
action table
+-----------+--------+------------+---------------+
| action_id | ref_no | date | action_status |
+-----------+--------+------------+---------------+
| 1 | 1 | 2018-09-20 | On-Going |
| 2 | 1 | 2018-09-22 | Finished |
| 3 | 3 | 2018-09-16 | On-Going |
| 4 | 4 | 2018-09-26 | On-Going |
| 5 | 4 | 2018-09-27 | Finished |
+-----------+--------+------------+---------------+
And need to get the following output
+-----------+-------------+------------+---------------+
| letter_id | description | date | action_status |
+-----------+-------------+------------+---------------+
| 1 | A | 2018-09-22 | Finished |
| 2 | B | - | Pending |
| 3 | C | 2018-09-16 | On-Going |
| 4 | D | 2018-09-27 | Finished |
+-----------+-------------+------------+---------------+
I used the following query
select letter.letter_id,letter.description, action.date, action.action_status
from letter
left join action on letter.letter_id=action.ref_no
where (date in
(
select max(date) from action
where letter.letter_id=action.ref_no
))
But the above query generate the following output
+-----------+-------------+------------+---------------+
| letter_id | description | date | action_status |
+-----------+-------------+------------+---------------+
| 1 | A | 2018-09-20 | On-Going |
| 1 | A | 2018-09-22 | Finished |
| 2 | B | - | Pending |
| 3 | C | 2018-09-16 | On-Going |
| 4 | D | 2018-09-26 | On-Going |
| 4 | D | 2018-09-27 | Finished |
+-----------+-------------+------------+---------------+
I can not understand what I am going wrong. Can anyone help me ?
DROP TABLE IF EXISTS action;
CREATE TABLE action
(action_id SERIAL PRIMARY KEY
,letter_id INT NOT NULL
,date DATE NOT NULL
,action_status VARCHAR(20) NOT NULL
);
INSERT INTO action VALUES
(1,101,'2018-09-20','On-Going'),
(2,101,'2018-09-22','Finished'),
(3,103,'2018-09-16','On-Going'),
(4,104,'2018-09-26','On-Going'),
(5,104,'2018-09-27','Finished');
SELECT x.*
FROM action x
JOIN
( SELECT letter_id, MAX(date) max_date FROM action GROUP BY letter_id ) y
ON y.letter_id = x.letter_id
AND y.max_date = x.date;
+-----------+-----------+------------+---------------+
| action_id | letter_id | date | action_status |
+-----------+-----------+------------+---------------+
| 2 | 101 | 2018-09-22 | Finished |
| 3 | 103 | 2018-09-16 | On-Going |
| 5 | 104 | 2018-09-27 | Finished |
+-----------+-----------+------------+---------------+
Presumably, you can figure out the rest

How to SELECT only the most recent of each group using SQL?

I have the following table:
TABLE sales
| id | name | date | amount |
|----|------|------------|--------|
| 1 | Mike | 2016-12-05 | 67.15 |
| 2 | Mike | 2016-12-09 | 98.24 |
| 3 | John | 2016-12-12 | 12.98 |
| 4 | Mike | 2016-12-19 | 78.48 |
| 5 | Will | 2016-12-19 | 175.26 |
| 6 | John | 2016-12-22 | 14.26 |
| 7 | John | 2016-12-23 | 13.48 |
I am trying to create a view that will group by the name column and return only the most resent amount. It should look like this:
TABLE sales_view
| id | name | date | amount |
|----|------|------------|--------|
| 4 | Mike | 2016-12-19 | 78.48 |
| 5 | Will | 2016-12-19 | 175.26 |
| 7 | John | 2016-12-23 | 13.48 |
I'm not sure how to go about making this. I would imagine I would need sub-queries, but I know that SQL get mad if you try to use them inside of views.
You can use a tuple and a subquery with group by for max(date)
select * from sales
where (name, date) in ( select name, max(date)
from sales
group by name)

SELECTing the contents of the Table, which is a result of another value

I have five tables.
Users
+--------+----------+---------------+
| UserID | Username | Password |
+--------+----------+---------------+
| 1 | Praveen | Praveen |
+--------+----------+---------------+
| 2 | Stack | StackOverflow |
+--------+----------+---------------+
| 3 | CrazyGuy | OhMyGawd! |
+--------+----------+---------------+
Messages
+-----------+-------------+-----------+----------------------------------------------+
| MessageID | MessageFrom | MessageTo | MessageContent |
+-----------+-------------+-----------+----------------------------------------------+
| 1 | 1 | 2 | Hi Stack! Praveen here! :) |
+-----------+-------------+-----------+----------------------------------------------+
| 2 | 1 | 3 | Hey Crazy Guy, you are spamming me!!! |
+-----------+-------------+-----------+----------------------------------------------+
| 3 | 2 | 3 | Hey, is Praveen speaking to you about spams? |
+-----------+-------------+-----------+----------------------------------------------+
Comments
+-----------+--------+----------------------------------------+
| CommentID | UserID | CommentContent |
+-----------+--------+----------------------------------------+
| 1 | 1 | Hello! This is Praveen! Stop spamming! |
+-----------+--------+----------------------------------------+
| 2 | 1 | Hey CrazyGuy, stop your spams!!! |
+-----------+--------+----------------------------------------+
| 3 | 3 | SPAM! SPAM!! SPAM!!! |
+-----------+--------+----------------------------------------+
IndexTable
+---------+-----------+------------+---------------------+
| IndexID | IndexType | IndexRowID | IndexTime |
+---------+-----------+------------+---------------------+
| 1 | 1 | 1 | 2015-04-10 10:50:00 |
+---------+-----------+------------+---------------------+
| 2 | 1 | 2 | 2015-04-10 10:55:00 |
+---------+-----------+------------+---------------------+
| 3 | 2 | 1 | 2015-04-10 11:25:00 |
+---------+-----------+------------+---------------------+
| 4 | 3 | 1 | 2015-04-10 11:30:00 |
+---------+-----------+------------+---------------------+
| 5 | 2 | 2 | 2015-04-10 11:45:00 |
+---------+-----------+------------+---------------------+
TableNames
+---------+-----------+
| TableID | TableName |
+---------+-----------+
| 1 | Users |
+---------+-----------+
| 2 | Messages |
+---------+-----------+
| 3 | Comments |
+---------+-----------+
I am more interested in the Index table to list all the activities. So, if I give a query like this:
SELECT *, (
SELECT `TableName` FROM `TableNames` WHERE `TableID`=`IndexType`
) AS `IndexTypeName` FROM `IndexTable` ORDER BY `IndexTime` DESC;
I would get all the contents like this:
+---------+-----------+------------+---------------------+------------+
| IndexID | IndexType | IndexRowID | IndexTime | IndexTable |
+---------+-----------+------------+---------------------+------------+
| 5 | 2 | 2 | 2015-04-10 11:45:00 | Messages |
+---------+-----------+------------+---------------------+------------+
| 4 | 3 | 1 | 2015-04-10 11:30:00 | Comments |
+---------+-----------+------------+---------------------+------------+
| 3 | 2 | 1 | 2015-04-10 11:25:00 | Messages |
+---------+-----------+------------+---------------------+------------+
| 2 | 1 | 2 | 2015-04-10 10:55:00 | Users |
+---------+-----------+------------+---------------------+------------+
| 1 | 1 | 1 | 2015-04-10 10:50:00 | Users |
+---------+-----------+------------+---------------------+------------+
If you see the result, the last column shows the Table Names and the concerned Primary Key (Item ID) of the table too. So, with the above result, I wanna add a column, that selects the main value from the table, with the ID specified.
In short, I would like the query to be:
SELECT *, (
SELECT `TableName` FROM `TableNames` WHERE `TableID`=`IndexType`
) AS `IndexTypeName`, (
SELECT {Username OR MessageContent OR CommentContent}
FROM {`IndexTypeName`}
WHERE {`UserID` OR `MessageID` OR `CommentID`} = `IndexRowID`
) AS `TableValue` FROM `IndexTable`
ORDER BY `IndexTime` DESC;
Is it possible with MySQL-Server?
using CASE WHEN:
SELECT *, (
SELECT `TableName` FROM `TableNames` WHERE `TableID`=`IndexType`
) AS `IndexTypeName`,
CASE
WHEN IndexType=1 THEN (SELECT Username FROM Users WHERE IndexRowID=UserID)
WHEN IndexType=2 THEN (SELECT MessageContent FROM Messages WHERE IndexRowID=MessageID)
WHEN IndexType=3 THEN (SELECT CommentContent FROM Comments WHERE IndexRowID=CommentID) END TableValue
ORDER BY `IndexTime` DESC;
The better solution is to put the data from those different tables in one table and use the typeid to separate them

Join table to itself to find products bought one after the other

I have a table which contains the following columns:
+------------------+----------+
| date_of_purchase | product |
+------------------+----------+
| 2013-06-18 | A |
| 2013-07-18 | A |
| 2013-08-24 | A |
| 2013-10-21 | A |
| 2013-11-20 | A |
| 2013-12-20 | A |
| 2014-01-20 | A |
| 2014-03-24 | A |
| 2014-03-24 | B |
| 2014-04-23 | B |
| 2014-04-23 | A |
| 2014-05-16 | B |
| 2014-05-23 | A |
+------------------+----------+
And I want to get something like this:
+----------+----------+------------+------------+
| product1 | product2 | date_a | date_b |
+----------+----------+------------+------------+
| A | B | 2014-01-20 | 2014-03-24 |
| A | B | 2014-03-24 | 2014-04-23 |
| B | A | 2014-05-16 | 2014-05-23 |
| A | B | 2014-04-23 | 2014-05-16 |
+----------+----------+------------+------------+
What I am trying to do is to check which product "B" is bought after product "A".
I am new to stack-overflow, so the way I am asking this question might seem vague. But need help on this one.
The derived table keeps track of the next purchase date using a variable which is then used to check whether a different product was purchased on the next purchase date
select t1.product, t2.product, t1.date_of_purchase, t2.date_of_purchase from (
select date_of_purchase, product,
#nextDateOfPurchase nextDateOfPurchase,
#nextDateOfPurchase := date_of_purchase
from Table1 t
order by date_of_purchase desc
) t1 join Table1 t2 on t2.date_of_purchase = t1.nextDateOfPurchase
and t2.product <> t1.product
and t2.date_of_purchase <> t1.date_of_purchase
order by t1.date_of_purchase
http://sqlfiddle.com/#!9/44b24/3