Access Database Query Grouping - ms-access

I have an Access 2003 database I've been asked to try and amend. My MS Access skills are limited hence this question.
The query looks like this:
SELECT
TBL_PropertyProgramMember.PropertyId,
Max(TBL_PropertyProgramMember.To) AS MaxOfTo,
TBL_PropertyProgramMember.BookingPriority
FROM
TBL_PropertyProgramMember
GROUP BY
TBL_PropertyProgramMember.PropertyId,
TBL_PropertyProgramMember.BookingPriority;
I need to return unique PropertyIds, the maximum To value for each property, and the BookingPriority associated with that maximum To value. Using the above grouping, I get multiple results if there property is listed more than once with different a different BookingPriority.
As I'm using grouping, I can't remove the BookingPriority grouping without Access throwing an error.
I'm sure this is to do with grouping, but I can't work out how to fix it. Just getting the maximum or minimum BookingPriority won't fix the problem because the value can change.

You have to compute your maximum (without returning your BookingPriority) and then join back to the results again, something like this:-
SELECT
TBL_PropertyProgramMember.PropertyID,
M.MaxTo,
TBL_PropertyProgramMember.BookingPriority
FROM
(
SELECT
TBL_PropertyProgramMember.PropertyID,
Max(TBL_PropertyProgramMember.To) AS MaxTo
FROM
TBL_PropertyProgramMember
GROUP BY
TBL_PropertyProgramMember.PropertyID
) AS M
INNER JOIN
TBL_PropertyProgramMember
ON (M.MaxTo = TBL_PropertyProgramMember.To)
AND (M.PropertyID = TBL_PropertyProgramMember.PropertyID);
You will need to handle cases where there is more than one record having the same maximum "To" column for a given BookingPriority.

Related

Transforming Results from Rows into Columns

I have a data set that contains both common and unique values, which I am attempting to return in a useable format to allow further analyse/work to be taken based on said results.
The desired result would be to have a script that would recognise the common values such as mpan/serial_number/read_at so as to only return a single row, but also to recognise the unique values those being the read_at and identifier.
Currently my script returns a unique row based on the identifier and the value, but I would like to be able to return a unique row for the read_at date for as many identifiers and values as are held. In most cases there are only two identifiers and values, but there could be as many as five.
The issue I have is that when I try to make distinct work, it will only then return the first found result, where I am expecting a pair of results at minimum. I am also unclear as to how I could stop getting a new row and instead create the result as an additional column?
My base script which pulls everything is as below, I have tried a few variances on this, but think this would likely be the best place to start from with regards to any help you may be able to offer?
SELECT *
FROM consumer.stg_d0010_v2_026_027
/*LEFT JOIN consumer.stg_d0010_v2_026_028_029
ON consumer.stg_d0010_v2_026_028_029.file_identifier = consumer.stg_d0010_v2_026_027.file_identifier
AND consumer.stg_d0010_v2_026_028_029.mpan = consumer.stg_d0010_v2_026_027.mpan*/
LEFT JOIN consumer.stg_d0010_v2_026_028_030_032
ON consumer.stg_d0010_v2_026_028_030_032.file_identifier = consumer.stg_d0010_v2_026_027.file_identifier
AND consumer.stg_d0010_v2_026_028_030_032.mpan = consumer.stg_d0010_v2_026_027.mpan
LEFT JOIN consumer.stg_d0010_v2_026_028_030_033
ON consumer.stg_d0010_v2_026_028_030_033.file_identifier = consumer.stg_d0010_v2_026_027.file_identifier
AND consumer.stg_d0010_v2_026_028_030_033.mpan = consumer.stg_d0010_v2_026_027.mpan
where consumer.stg_d0010_v2_026_028_030_032.read_At > '2022-10-01'
and consumer.stg_d0010_v2_026_027.mpan in (
)
Example dataset in image below.
enter image description here
And desired outcome
enter image description here
The issue I have is that when I try to make distinct work, it will only then return the first found result, where I am expecting a pair of results at minimum. I am also unclear as to how I could stop getting a new row and instead create the result as an additional column?

Select last row from a MySQL query

I have a query that returns some dates which are not in any order. I need to select the last row from the sub query. The problem is all the solutions I can find online uses something like
ORDER BY qry_doc_dates.arrival_date DESC LIMIT 1
Select qry_doc_dates.arrival_date
FROM (qry_doc_date) AS qry_doc_dates
ORDER BY qry_doc_dates.arrival_date DESC
LIMIT 1
which will not serve my purpose because it first orders the dates as DESC(or ASC).
Suppose the qry_doc_date returns :
"2019-05-27",
"2019-05-13",
"2019-05-20",
"2019-05-22",
"2019-07-12",
"2019-05-22",
"2019-07-16",
"2019-05-22"
As we can see that the returned values are not in order. If I use
ORDER BY qry_doc_dates.arrival_date DESC LIMIT 1
then it returns "2019-07-16" But I need "2019-05-22" which is the last row.
EDIT 1:
I am trying to convert this VBA query to MYSQL.
DLast("arrival_date", "qry_doc_date", "[package_id] = " & Me!lstPackage)
I suppose I misunderstood what the VBA query wants to return. Another issue is I do not have means to run this VBA query and check the result myself.
Your question doesn't make too much sense according to the SQL standard. In the absense of an ORDER BY clause the database engine is free to return the rows in any order. This order may even change over time.
So essentially you are requesting the "last random row" the query returns. If this is the case, why don't you get the "first random row"? It doesn't make any difference, does it?
The only way of getting the last random row is to get them all and discard all of them except for the last one.
Now, if you just need one random row, I would suggest you just get the first random row, and problem solved.
In response to the additional information from your edit:
EDIT 1: I am trying to convert this VBA query to MYSQL.
DLast("arrival_date", "qry_doc_date", "[package_id] = " & Me!lstPackage)
I suppose I misunderstood what the VBA query wants to return. Another
issue is I do not have means to run this VBA query and check the
result myself.
Unless your dataset qry_doc_date is ordered by means of an order by clause, the DFirst or DLast domain aggregate functions will return essentially a random record.
This is stated in the MS Access Documentation for these two functions:
You can use the DFirst and DLast functions to return a random record from a particular field in a table or query when you simply need any value from that field.
[ ... ]
If you want to return the first or last record in a set of records (a domain), you should create a query sorted as either ascending or descending and set the TopValues property to 1. For more information, see the TopValues property topic. From a Visual Basic for Applications (VBA) module, you can also create an ADO Recordset object and use the MoveFirst or MoveLast method to return the first or last record in a set of records.
What you need is to in qry_doc_date to include a sequential row number.
Then you can use something like this:
ORDER BY qry_doc_dates.row_number DESC LIMIT 1

Access query using calculation

I'm trying to make a query using a calculation with Date().
I have a field named [Currentordue] and a field named [duedate]. What I'm trying to accomplish is making a query to limit the results by "if [currentordue] equals "due" or if [duedate] minus today's date is less than 30 days."
I've tried a few different ways but always seem to end with either an error or with no results showing (which would be an error as well since I know there are fields that are due).
Any and all help would be appreciated.
Here is a way to use two different date conditions:
SELECT Table1.Currentordue, Table1.duedate, DateDiff("d",[duedate],Date()) AS Expr1
FROM Table1
WHERE (((DateDiff("d",[duedate],Date()))<30)) OR (((Table1.Currentordue)=[duedate]));

Sum Function brings up box to input value

Working with Access SQL queries and when I enter a sum function instead of returning the sum of the values it brings up a box asking me to input a number. The entire code is trying to return the transactions that contain more than five products.
SELECT SoldVia.TID, sum(SoldVia.NoOfItems) as "TotalSold"
From SalesTransaction INNER JOIN SoldVia ON SalesTransaction.TID = SoldVia.TID
Group By SoldVia.ProductID, SoldVia.TID
Having TotalSold>5;
I think you need to change the Having statement to the following:
Having Sum(SoldVia.NoOfItems)>5
At the moment Access is treating the TotalSold as an implicit parameter which is why it is asking for a value when the query is run.

Datediff & Group By not working?

I'm trying to build a query (QueryB) for it to be referenced in my MS Access control. I know I got the source expression syntax right, I have a very similar working control with QueryA.
I only changed the field and query names. However I keep getting the infamous #Name? error with QueryB. The difference between QueryA and QueryB is the SQL code. QueryA has a GROUP BY and SUM() and QueryB only has DATEDIFF(). I have tried adding the GROUP BY to QueryB, but kept getting [...execute query does not include the specified expression as part of aggregate function].
Query B:
SELECT IIF(DATEDIFF("d",Date_X,Date_Y)>100),
ROUND(IIF(DATEDIFF("d",Date_X,Date_Y)/30,2),
DATEDIFF("d",Date_X,Date_Y)
AS DATEDIFF_X_Y
FROM LAB_DATES GROUP BY LAB_DATES.ID;
This is in MS Access SQL.
ControlB source referencing QueryB in MS Access:
=DLookUp("[DATE_DIFF_X_Y]",
"[QueryB]",
"[LAB_DATES.ID] = " & [Forms]![Lab Results Form]![Textbox_DATE_ID])
When taking out the GROUP BY, this query runs fine but I get the #Name? error in the control. All data is from ODBC MySQL. Access is the front end.
Edit: I can just drop GROUP BY. But I will get the #Name? error. My goal is to display the date difference between Date_X and Date_Y.
[...execute query does not include the specified expression as part
of aggregate function]
That error message already indicates that using GROUP BY does not work with aggregate Functions.
DATEDIFF() is an aggregate function and does not work with a GROUP BY.
The reason for that is that GROUP BY reduces your dataresult and only displays one line per different entry of the column you are using.
What is your aim for that query anyways? I am sure there is a different solumtion for that problem. GROUP BY DATE.ID sounds like you are making a GROUP BY on the primary key which has no effect, because primary keys are unique per definition.
I think your problem is within your DLookup rather than your query. You do not need the GROUP BY at all, this will cause the query to error, you can simply make QueryB:
SELECT IIF(DATEDIFF("d",Date_X,Date_Y)>100),
ROUND(IIF(DATEDIFF("d",Date_X,Date_Y)/30,2),
DATEDIFF("d",Date_X,Date_Y) AS DATEDIFF_X_Y
FROM LAB_DATES;
The problem is that in your DLookup you are using:
[LAB_DATES.ID]
Where you actually want
[LAB_DATES].[ID]
i.e. In it's current form you are looking for a column called LAB_DATES.ID rather than a Column called ID in the object LAB_DATES. Changing your DLookup to this:
=DLookUp("[DATE_DIFF_X_Y]",
"[QueryB]",
"[LAB_DATES].[ID] = " & [Forms]![Lab Results Form]![Textbox_DATE_ID])
Should do the trick.