Access Select Max date with corresponding records - ms-access

I am trying to create a query that looks at the most recent date and return the corresponding values. Using the max function works only if I have the hose part no and max inspection columns and nothing else. Once I add in the scrap amount columns it duplicates the hose part no column. I only want one single record per hose part no.
Below is an example of what is going on:
Hose Part No Max Inspection Date scrapamt1 scrapamt2 scrapamt3 scrapamt4

If I understand you correct, this is what you want:
Select * From Table1 Inner Join
(Select Table1.[Hose Part No], Max(Table1.[Max Inspection Date]) As [MaxOfMax Inspection Date] From Table1 Group By Table1.[Hose Part No]) As MaxValues
On Table1.[Hose Part No] = MaxValues.[Hose Part No] And Table1.[Max Inspection Date] = MaxValues.[MaxOfMax Inspection Date]
A subquery (named MaxValues) is used to determine the maximum Max Inspection Date per Hose Part No and will be joined to the same table.
Because you also didn't mention the table Name, I choosed Table1.

This appears to be working -
tblReleaseNo:
| Release No | Hose Part No | Release Date | Due Date |
|------------|--------------|--------------|------------|
| 1 | Hose 1 | 01/01/2018 | 01/01/2018 |
| 2 | Hose 1 | 01/01/2018 | 01/01/2018 |
| 3 | Hose 2 | 01/01/2018 | 01/01/2018 |
| 4 | Hose 2 | 01/01/2018 | 01/01/2018 |
| 5 | Hose 3 | 01/01/2018 | 01/01/2018 |
NewScrapTble:
| Release No | Inspect Date | scrapamt1 | reason1 | scrapamt2 |
|------------|--------------|-----------|---------|-----------|
| 1 | 01/12/2018 | 10 | | 15 |
| 2 | 12/12/2018 | 15 | | 18 |
| 3 | 01/07/2018 | 12 | | 12 |
| 4 | 01/08/2018 | 14 | | 200 |
| 5 | 01/03/2017 | 22 | | 20 |
SQL:
SELECT [Hose Part No]
, MAX([Inspect Date]) AS Inspect
, LAST(scrapamt1) AS Amount1
, LAST(scrapamt2) AS Amount2
FROM (
SELECT [Hose Part No]
, [Inspect Date]
, scrapamt1
, scrapamt2
FROM tblReleaseNo INNER JOIN NewScrapTble ON
tblReleaseNo.[Release No] = NewScrapTble.[Release No]
)
GROUP BY [Hose Part No]
Final Table:
| Hose Part No | Inspect | Amount1 | Amount2 |
|--------------|------------|---------|---------|
| Hose 1 | 12/12/2018 | 15 | 18 |
| Hose 2 | 01/08/2018 | 14 | 200 |
| Hose 3 | 01/03/2017 | 22 | 20 |
Note: I'm not 100% sure that LAST is correct, it is pulling the correct amounts but not sure if it will trip up on some records?

Related

How to sum values of two tables and group by date

I am building a trading system where users need to know their running account balance by date for a specific user (uid) including how much they made from trading (results table) and how much they deposited or withdrew from their accounts (adjustments table).
Here is the sqlfiddle and tables: http://sqlfiddle.com/#!9/6bc9e4/1
Adjustments table:
+-------+-----+-----+--------+------------+
| adjid | aid | uid | amount | date |
+-------+-----+-----+--------+------------+
| 1 | 1 | 1 | 20 | 2019-08-18 |
| 2 | 1 | 1 | 50 | 2019-08-21 |
| 3 | 1 | 1 | 40 | 2019-08-21 |
| 4 | 1 | 1 | 10 | 2019-08-19 |
+-------+-----+-----+--------+------------+
Results table:
+-----+-----+-----+--------+-------+------------+
| tid | uid | aid | amount | taxes | date |
+-----+-----+-----+--------+-------+------------+
| 1 | 1 | 1 | 100 | 3 | 2019-08-19 |
| 2 | 1 | 1 | -50 | 1 | 2019-08-20 |
| 3 | 1 | 1 | 100 | 2 | 2019-08-21 |
| 4 | 1 | 1 | 100 | 2 | 2019-08-21 |
+-----+-----+-----+--------+-------+------------+
How do I get the below results for uid (1)
+--------------+------------+------------------+----------------+------------+
| ResultsTotal | TaxesTotal | AdjustmentsTotal | RunningBalance | Date |
+--------------+------------+------------------+----------------+------------+
| - | - | 20 | 20 | 2019-08-18 |
| 100 | 3 | 10 | 133 | 2019-08-19 |
| -50 | 1 | - | 84 | 2019-08-20 |
| 200 | 4 | 90 | 378 | 2019-08-21 |
+--------------+------------+------------------+----------------+------------+
Where RunningBalance is the current account balance for the particular user (uid).
Based on #Gabriel's answer, I came up with something like, but it gives me empty balance and duplicate records
SELECT SUM(ResultsTotal), SUM(TaxesTotal), SUM(AdjustmentsTotal), #runningtotal:= #runningtotal+SUM(ResultsTotal)+SUM(TaxesTotal)+SUM(AdjustmentsTotal) as Balance, date
FROM (
SELECT 0 AS ResultsTotal, 0 AS TaxesTotal, adjustments.amount AS AdjustmentsTotal, adjustments.date
FROM adjustments LEFT JOIN results ON (results.uid=adjustments.uid) WHERE adjustments.uid='1'
UNION ALL
SELECT results.amount AS ResultsTotal, taxes AS TaxesTotal, 0 as AdjustmentsTotal, results.date
FROM results LEFT JOIN adjustments ON (results.uid=adjustments.uid) WHERE results.uid='1'
) unionTable
GROUP BY DATE ORDER BY date
For what you are asking you would want to union then group the results from both tables, this should give the results you want. However, I recommend calculating the running balance outside of MySQL since this adds some complexity to our query.
Weird things could start to happen, for example, if someone already defined the #runningBalance variable as part of the queries scope.
SELECT aggregateTable.*, #runningBalance := ifNULL(#runningBalance, 0) + TOTAL
FROM (
SELECT SUM(ResultsTotal), SUM(TaxesTotal), SUM(AdjustmentsTotal)
, SUM(ResultsTotal) + SUM(TaxesTotal) + SUM(AdjustmentsTotal) as TOTAL
, date
FROM (
SELECT 0 AS ResultsTotal, 0 AS TaxesTotal, amount AS AdjustmentsTotal, date
FROM adjustments
UNION ALL
SELECT amount AS ResultsTotal, taxes AS TaxesTotal, 0 as AdjustmentsTotal, date
FROM results
) unionTable
GROUP BY date
) aggregateTable

Converting lump sums to transactions

I have a database that tracks the size of claims.
Each claim has fixed information that is stored in claim (such as claim_id and date_reported_to_insurer).
Each month, I get a report which is added to the table claim_month. This includes fields such as claim_id, month_id [101 is 31/01/2018, 102 is 28/02/2018, etc] and paid_to_date.
Since most claims don't change from month to month, I only add a record for claim_month when the figure has changed since last month. As such, a claim may have a June report and an August report, but not a July report. This would be because the amount paid to date increased in June and August, but not July.
The problem that I have now is that I want to be able to check the amount paid each month.
Consider the following example data:
+----------------+----------+----------------+--------------+
| claim_month_id | claim_id | month_id | paid_to_date |
+----------------+----------+----------------+--------------+
| 1 | 1 | 6 | 1000 |
+----------------+----------+----------------+--------------+
| 5 | 1 | 7 | 1200 |
+----------------+----------+----------------+--------------+
| 7 | 2 | 6 | 500 |
+----------------+----------+----------------+--------------+
| 12 | 1 | 9 | 1400 |
+----------------+----------+----------------+--------------+
| 18 | 2 | 8 | 600 |
+----------------+----------+----------------+--------------+
If we assume that this is all of the information regarding claim 1 and 2, then that would suggest that they are both claims that occurred during June 2018. Their transactions should look like the following:
+----------------+----------+----------------+------------+
| claim_month_id | claim_id | month_id | paid_month |
+----------------+----------+----------------+------------+
| 1 | 1 | 6 | 1000 |
+----------------+----------+----------------+------------+
| 5 | 1 | 7 | 200 |
+----------------+----------+----------------+------------+
| 7 | 2 | 6 | 500 |
+----------------+----------+----------------+------------+
| 12 | 1 | 9 | 200 |
+----------------+----------+----------------+------------+
| 18 | 2 | 8 | 100 |
+----------------+----------+----------------+------------+
The algorithm I'm using for this is
SELECT claim_month_id,
month_id,
claim_id,
new.paid_to_date - old.paid_to_date AS paid_to_date_change,
FROM claim_month AS new
LEFT JOIN claim_month AS old
ON new.claim_id = old.claim_id
AND ( new.month_id > old.month_id
OR old.month_id IS NULL )
GROUP BY new.claim_month_id
HAVING old.month_id = Max(old.month_id)
However this has two issues:
It seems really inefficient at dealing with claims with multiple
records. I haven't run any benchmarking, but it's pretty obvious.
It doesn't show new claims. In the above example, it would only show lines 2, 3 and 5.
Where am I going wrong with my algorithm, and is there a better logic to use to do this?
Use LAG function to get the next paid_to_date of each claim_id, and use the current paid_to_date minus the next paid_to_date.
SELECT
claim_month_id,
claim_id,
month_id,
paid_to_date - LAG(paid_to_date, 1, 0) OVER (PARTITION BY claim_id ORDER BY month_id) AS paid_month
FROM claim
The output table is:
+----------------+----------+----------+------------+
| claim_month_id | claim_id | month_id | paid_month |
+----------------+----------+----------+------------+
| 1 | 1 | 6 | 1000 |
| 5 | 1 | 7 | 200 |
| 12 | 1 | 9 | 200 |
| 7 | 2 | 6 | 500 |
| 18 | 2 | 8 | 100 |
+----------------+----------+----------+------------+

How to identify entries that have not changed over time?

I am trying to identify names that have not had a total score change over a period of time, and what that period of time was.
Example Table:
+----------+--------+-------+
| Date | Name | Score |
+----------+--------+-------+
| 1/1/2016 | Frank | 55 |
| 1/1/2016 | John | 80 |
| 1/2/2016 | Frank | 60 |
| 1/2/2016 | John | 85 |
| 1/3/2016 | Frank | 60 |
| 1/3/2016 | John | 100 |
| 1/4/2016 | Frank | 60 |
| 1/4/2016 | John | 120 |
| 1/5/2016 | Frank | 60 |
| 1/5/2016 | John | 120 |
+----------+--------+-------+
Expected Output:
+-------+------+
| Name | Days |
+-------+------+
| Frank | 4 |
| John | 2 |
+-------+------+
I have been trying to puzzle out how to do this with no success. I have no code to show since none of it has even been close to successful and would only serve to clutter up the question.
How can I go about doing this?
You need to group the data with the score, and then calculate the first and last day that the user has that score, check this:
SELECT DATEDIFF(last_day, first_day) + 1 AS days, name, score,
first_day, last_day
FROM (
SELECT
max(date_score) as last_day,
min(date_score) as first_day,
score,
name
FROM members
GROUP by score
) AS score
The Date diff function return the difference between two DATE's, we add one to represent that the score last one day.
Check here for a working example link

MySQL select a row from a daterange excluding the year

I'm trying to create a MySQL query to select the daily price from a table that is between a date range from another. I only want to use 'starting-ending' months and days from the table "seasons" and I want to pass the year dynamically to the query.
This is my query: (I'm giving it the Year to exclude the one on the table)
SELECT a.season, b.base_price
FROM seasons a
JOIN pricebyseason b ON a.id=b.season_id
WHERE b.prop_id='6' AND '2015-11-29' BETWEEN DATE_FORMAT(a.starting,'2015-%m-%d') AND DATE_FORMAT(a.ending,'2016-%m-%d')
ORDER BY b.base_price DESC
It works but not with all dates.
These are the tables:
seasons (these are static date values)
+----+--------------+------------+------------+
| id | season | starting | ending |
+----+--------------+------------+------------+
| 1 | Peak Season | 2015-12-11 | 2016-01-09 |
| 2 | High Season | 2015-11-27 | 2016-04-15 |
| 3 | Mid Season | 2015-04-16 | 2015-09-01 |
| 4 | Low Season | 2015-09-02 | 2015-11-26 |
| 5 | Spring Break | 2015-03-05 | 2015-03-21 |
+----+--------------+------------+------------+
pricebyseason
+----+---------+-----------+------------+
| id | prop_id | season_id | base_price |
+----+---------+-----------+------------+
| 1 | 6 | 1 | 950 |
| 2 | 6 | 2 | 750 |
| 3 | 6 | 3 | 450 |
| 4 | 6 | 4 | 400 |
| 5 | 6 | 5 | 760 |
+----+---------+-----------+------------+
What I want to achive is query the dialy price between checkin, checkout selection
I create this sqlfiddle: http://sqlfiddle.com/#!9/4a6f4
This is a previuos query that is not working either:
SELECT a.base_price,b.season,b.starting,b.ending
FROM pricebyseason a JOIN seasons b ON a.season_id=b.id
WHERE a.prop_id='6' AND
(DATE_FORMAT(b.starting,'%m-%d') <= '12-27' OR DATE_FORMAT(b.starting,'2016-%m-%d') >= '2015-12-27')
AND
(DATE_FORMAT(b.ending,'%m-%d') >= '12-27' OR DATE_FORMAT(b.ending,'2016-%m-%d') <= '2015-12-27')
ORDER BY base_price DESC
And here are some sample dates for each season: '2016-01-08','2015-12-27','2016-04-14','2015-11-29','2016-04-15','2015-09-01','2016-09-02','2015-11-26','2016-10-10','2016-03-18','2016-06-22','2015-06-15'
Thank a lot

MySQL monthly report inaccuracies

My company has introduced an on-call rota for the IT department. I created a MySQL table which details who takes on-call, when they take it and when it's taken by the next individual on completion of each shift.
Below is a sample (with names removed) taken from late May - early June:
|seq__num | date_taken | date_relinquished | user |
|-----------|---------------|-----------------------|-----------|
| 1 | 2015-05-29 | 2015-06-05 | A |
| 2 | 2015-06-05 | 2015-06-06 | B |
| 3 | 2015-06-06 | 2015-06-07 | C |
| 4 | 2015-06-07 | 2015-06-10 | B |
| 5 | 2015-06-10 | 2015-06-10 | A |
| 6 | 2015-06-10 | 2015-06-12 | B |
| 7 | 2015-06-12 | 2015-06-19 | C |
| 8 | 2015-06-19 | 2015-07-03 | D |
The next step is to produce an automated monthly report which queries the table and outputs how many days each user held on-call for so Finance know how much they need paying. Currently this is counted manually.
The query I've got is:
SELECT user, SUM(DATEDIFF(date_relinquished, date_taken))
AS duration
FROM on-call_log
WHERE YEAR(date_relinquished) = YEAR(CURRENT_DATE - INTERVAL 1 MONTH)
AND MONTH(date_relinquished) = MONTH(CURRENT_DATE - INTERVAL 1 MONTH)
GROUP BY user
While this does work if on-call is held perfectly within a month. If someone is on-call from the one month into the next, it reports the full period, which produces inaccuracies. Instead of reporting as if June actually has 30 days, like so:
A 4
B 6
C 8
D 12
It takes into account how person A took on-call from the previous month and person D took it into the following month, like so:
A 7
B 6
C 8
D 14
I'm a bit of a loss as to how to make it report accurately. Does anyone have any suggestions or ideas? Thanks in advance.
One solution is to use a calendar table - even a calendar table holding all plausible dates into the future is depressingly small!
Then your query might look like this - I've assumed that on-calls are only counted once per day per user (DISTINCT)...
SELECT user
, DATE_FORMAT(dt,'%Y-%m') month
, COUNT(DISTINCT dt) total
FROM calendar x
JOIN my_table y
ON x.dt BETWEEN y.date_taken AND y.date_relinquished
GROUP
BY month
, user;
+------+---------+-------+
| user | month | total |
+------+---------+-------+
| A | 2015-05 | 3 |
| A | 2015-06 | 6 |
| B | 2015-06 | 8 |
| C | 2015-06 | 10 |
| D | 2015-06 | 12 |
| D | 2015-07 | 3 |
+------+---------+-------+