Access VBA: Get difference in value between current and previous record - sql

I have made report based on query according to this link:
http://www.techonthenet.com/access/queries/max_query2.php
It gives me list of records with values:
(primaryKey)
ID.......FirstNum....SecNum.....Diameter.....Owner
1........100200.......01...............150..............Peter
2........100200.......02...............138..............Peter
3........100300.......07...............112..............John
Query sorts records in descending order by Diametral. I want make new column which will count difference between first and second record, then between third and second and so on. Like this:
(primaryKey)
ID.......FirstNum....SecNum.....Diameter.....DiffDiametral.....Owner
1........100200.......01...............150.......................................Peter
2........100200.......02...............138.............12......................Peter
3........100300.......07...............112.............26.....................John
What should I write into RowSource or DataSource for DiffDiametral to get these values? How can I avoid error for first line, where is not previous value which I want substract from?
I tried to solve it according to this link:
http://support.microsoft.com/kb/101081/en-us
but I did not solve it. Simply I dont know how I can refer previous value of Diameter to count difference.

Based on your information, a subquery should do it. Just substitute your actual table name for tblDiameters.
SELECT C.ID, C.FirstNum, C.SecNum, C.Diameter, C.Owner,
(SELECT TOP 1 P.Diameter
FROM tblDiameters AS P
WHERE P.Diameter < C.Diameter
ORDER BY P.Diameter DESC )
- C.Diameter AS DiffDiameter
FROM tblDiameters AS C

Related

Returning Only Latest Result For Location in SQL [duplicate]

This question already has answers here:
How do I limit the number of rows returned by an Oracle query after ordering?
(14 answers)
Closed last year.
I'm wanting to find the very last pallet placed in a given batch of locations within a warehouse.
I currently have:
SELECT
max(datreg) AS "_Reg Date",
logguser,
mha,
rack,
horcoor,
vercoor
FROM
L16T3
WHERE
l16lcode = '3'
AND
rack = #('Rack?',rack)
AND
horcoor >= #('Loc From?',horcoor)
AND
horcoor <= #('Loc To?',horcoor)
ORDER BY 1
LIMIT 1
I thought this would return just the last pallet placed in that specific location, but I'm still getting like 4 entries for one location.
I would only want the highlighted result, as that is the most recent pallet placed in 110-001-04:
I'm sure this is super simple but im just starting out :)
You can use a combination of ORDER BY and LIMIT to achieve what you want.
Limit
In a lot of other databases, this is called LIMIT, but I missed that you are using an Oracle database, which has a different dialect of SQL. In Oracle, the most direct equivilent of a limit is:
FETCH FIRST n ROWS ONLY
This means that your query can return at most n rows. So, for example, FETCH FIRST 1 ROWS ONLY means that it can return at most 1 row. The issue is that it takes rows from the start of the table, not the end (and despite the wording implying FETCH LAST n ROWS ONLY would be a thing, it doesn't seem to be) --- you can essentially think of it as cutting off the rows below given limit.
For example, if I have rows in order "A", "B", and "C", FETCH FIRST 1 ROWS ONLY only returns "A". If "C" was really the one I wanted (e.g. the row at the bottom), then I would need to add an ORDER BY clause to first order the results so that the one I want is at the top.
Order By
ORDER BY column dir orders your results by a specific column in a specific direction, e.g. in ascending (ASC) or descending (DESC) order. The syntax actually allows for more complex ordering (e.g. ordering by multiple columns or by a function), but for this simple case this should do what we need.
Putting it together
You want to order so that your desired row is at the top of your table, then you want to limit your results set to contain at most one row.
Adding something like this to the end of your query should work:
ORDER BY "_Reg Date" DESC
FETCH FIRST 1 ROWS ONLY

SQL- Need to Order By date first and then have a specific variable value always come first

I need to order by results to order by date first but then to have a specific variable value (trackingbasisID=4) to always be ordered first. Below is an example. I have many variables in the select statement.I've also attached the graph of how results are shown. We'd liked to avoid the W in the graph s so we want the delay (TrackingBasisID=4) to always display first over all other id's but still sort by date first. My Current OrderBy Statement is simply:
ORDER BY hd.Date ASC, hd.PreimPhaseNumber ASC
There are trackingbasis ID of 1,2,3,4,5,6 -- Of which We always want 4 to come first when being ordered.

How to count unique occurences of string in table for separate records in apex 5

I am trying to automatically count the unique occurrences of a string saved in the table. Currently I have a count of a string but only when a user selects the string and it gives every record the same count value.
For example
Below is a image of my current table:
From the image you can see that there is a Requirement column and a count column. I have got it to the point were when the user would select a requirement record (each requirement record has a link) it would insert the requirement text into a requirement item called 'P33_REQUIREMENT' so the count can have a value to compare to.
This is the SQL that I have at current:
SELECT (SELECT COUNT(*)
FROM DIA_ASSOCIATED_QMS_DOCUMENTS
WHERE REQUIREMENT = :P33_REQUIREMENT
group by REQUIREMENT
) AS COUNT,
DPD.DIA_SELECTED,
DPD.Q_NUMBER_SELECTED,
DPD.SECTION_SELECTED,
DPD.ASSIGNED_TO_PERSON,
DAQD.REFERENCE,
DAQD.REQUIREMENT,
DAQD.PROGRESS,
DAQD.ACTION_DUE_DATE,
DAQD.COMPLETION_DATE,
DAQD.DIA_REF,
DA.DIA,
DA.ORG_RISK_SCORE
FROM DIA_PROPOSED_DETAIL DPD,
DIA_ASSOCIATED_QMS_DOCUMENTS DAQD,
DIA_ASSESSMENTS DA
WHERE DPD.DIA_SELECTED = DAQD.DIA_REF
AND DPD.DIA_SELECTED = DA.DIA
This is the sql used to make the table in the image.
This issue with this is, it is giving every record the same count when the user selects a requirement value. I can kind of fix this by also adding in AND DIA_SELECTED = :P33_DIA into the where clause of the count. DIA_SELECTED being the first column in the table and :P33_DIA being the item that stores the DIA ref number relating to the record chosen.
The output of this looks like:
As you can see there is only one count. Still doesn't fix the entire issue but a bit better.
So to sum up is there a way to have the count, count the occurrences individually and insert them in the requirements that are the same. So if there are three tests like in the images there would be a '3' in the count column where requirement = 'test', and if there is one record with 'test the system' there would be a '1' in the count column.
Also for more context I wont know what the user will input into the requirement so I can't compare to pre-determined strings.
I'm new to stack overflow I am hoping I have explained enough and its not too confusing.
The following extract:
SELECT (SELECT COUNT(*)
FROM DIA_ASSOCIATED_QMS_DOCUMENTS
WHERE REQUIREMENT = :P33_REQUIREMENT group by REQUIREMENT ) AS COUNT
Could be replaced by
SELECT (SELECT COUNT(*)
FROM DIA_ASSOCIATED_QMS_DOCUMENTS
WHERE REQUIREMENT = DAQD.REQUIREMENT ) AS COUNT
Which would give you - for each line, the number of requirements that are identical.
I'm not completely certain it is what you are after, but if it isn't, it should give you some ideas on how to progress (or allow you to indicate where I failed to understand your request)

SQL - How to insert a subquery into a query in order to retrieve unique values

I am writing reports using Report Builder 3, and I need some help with an sql query to get unique values.
Using the following sample data:
I need to be able to get one single value for feeBudRec returned for each feeRef. The value of each feeBudRec is always the same for each individual feeRef (eg for every data row for feeRef LR01 will have a feeBudRec of 1177).
The reason why I need to get a single feeBudRec value for each feeRef is that I need to be able to total the feeBudRec value for each feeRef in a feePin (eg for feePin LEE, I need to total the feeBudRec values for LR01 and PS01, which should be 1177 + 1957 to get a total of 3134; but if I don't have unique values for feeBudRec, it will add the values for each row, which would bring back a total of 11756 for the 8 LEE rows).
My experience with writing SQL queries is very limited, but from searching the internet, it looks like I'll need to put in a subquery into my SQL query in order to get a single unique feeBudRec figure for each feeRef, and that a subquery that gets a minimum feeBudRec value for each feeRef should work for me.
Based on examples I've found, I think the following subquery should work:
SELECT a.feeRef, a.feeBudRec
FROM (
SELECT uvw_EarnerInfo.feeRef, Min(uvw_EarnerInfo.feeBudRec) as AvailableTime
FROM uvw_EarnerInfo
GROUP BY
uvw_EarnerInfo.feeRef
) as x INNER JOIN uvw_EarnerInfo as a ON a.feeRef = x.feeRef AND a.feeBudRec = x.AvailableTime;
The problem is that I have no idea how to insert that subquery into the query I'm using to produce the report (as follows):
SELECT
uvw_EarnerInfo.feeRef
,uvw_EarnerInfo.PersonName
,uvw_EarnerInfo.PersonSurname
,uvw_EarnerInfo.feePin
,uvw_RB_TimeLedger.TimeDate
,uvw_RB_TimeLedger.matRef
,uvw_RB_TimeLedger.TimeTypeCode
,uvw_RB_TimeLedger.TimeCharge
,uvw_RB_TimeLedger.TimeElapsed
,uvw_WoffTimeByTime.WoffMins
,uvw_WoffTimeByTime.WoffCharge
,uvw_EarnerInfo.feeBudRec
,uvw_EarnerInfo.personOccupation
FROM
uvw_RB_TimeLedger
LEFT OUTER JOIN uvw_WoffTimeByTime
ON uvw_RB_TimeLedger.TimeId = uvw_WoffTimeByTime.TimeId
RIGHT OUTER JOIN uvw_EarnerInfo
ON uvw_EarnerInfo.feeRef = uvw_RB_TimeLedger.feeRef
WHERE
uvw_RB_TimeLedger.TimeDate >= #TimeDate
AND uvw_RB_TimeLedger.TimeDate <= #TimeDate2
If that subquery will get the correct results, can anyone please help me with inserting it into my report query. Otherwise, can anyone let me know what I will need to do to get a unique feeBudRec value for each feeRef?
Depends on the exact schema, but assuming the uvw_EarnerInfo lists the Pin, Ref, and Rec without duplicates, try adding an extra column (after personOccupation) on the end of your query such as :
feeBudRecSum = (Select SUM(FeeBudRec) From uvw_EarnerInfo x
where x.feePin = uvw_EarnerInfo.feePin
Group By x.FeePin)
Note that you would not Sum these values in your report. This column should have the total you are looking for.
The key to Report Builder is to get your query correct from the offset and let the wizard then structure your report for you. It takes all the hard work out of structuring your report manually.
I haven't used Report Builder for a while now but in the query builder of the report displaying the graphical representation of your query you should be able to drag and drop columns in and out of the query set. Dragging a column upwards and out of the box (showing your columns) would have the effect of causing your report to break on this column.
If you restructure this way you will probably have to run the report generator again to regenerate the report and restructure it.
Once you are happy with the structure you can then begin to add the summary columns.

"Totals" Query: show last non-blank string

I have a totals query (one where I clicked the totals button, and it has "group by" columns) in Access 2007. Most of the columns are fine... group by columns, max columns, min columns, etc. For some of them though, I want to extract only the last non-blank (not "" or null) value of a string column.
Here's a sample of what my SQL looks like:
SELECT Min(Duplicates.AttendedODBefore) AS AttendedODBefore,
Min(Duplicates.ContactByPost) As ContactByPost,
Last(Duplicates.PlannedStart) As PlannedStart,
Min(Duplicates.AccessibilityRequirements) AS AccessibilityRequirements,
Last(Duplicates.UcasNumber) As UcasNumber
-- ^^^^
FROM DuplicateStudents As Duplicates
GROUP BY
Duplicates.ID
The expression highlighted is the one I want changing to the last non-blank field. Is there an Access-specific or plain SQL expression which will do this?
Edit: Turns out that Min() and Max() work on string values and ignores null values, taking the first and last values alphabetically. It's not perfect, because it doesn't guarantee that the value selected is the last one, but it's better than just a load of nulls which is what using Last() might give.
Access seems resistant to the idea of returning the last non-null value in a query using GROUP BY. Even if your FROM clause were modified to be something like
FROM (
SELECT allfieldsyouneed
FROM DuplicateStudents
ORDER BY PlannedStart
) AS SortedDuplicates
and the rest of your query were modified to use SortedDuplicates instead, Access doesn't seem to return the last value based on the order you specify. I tested on a table with exactly one blank row and specific orders that I could verify (both an auto-increment field and a value that I checked by using Min and Max), and Access chose to return some other value as Last.
Based on your comment it seems like your definition of "Last" is: the most recently added record, based on an auto-incrementing ID. As such, some form of the following should work (it uses a subquery to return the most recent non-null UcasNumber):
SELECT Min(Duplicates.AttendedODBefore) AS AttendedODBefore,
Min(Duplicates.ContactByPost) As ContactByPost,
Last(Duplicates.PlannedStart) As PlannedStart,
Min(Duplicates.AccessibilityRequirements) AS AccessibilityRequirements,
(SELECT TOP 1 D.UcasNumber FROM Duplicates AS D
WHERE D.UcasNumber Is Not Null
ORDER BY D.ID DESC) As UcasNumber
FROM DuplicateStudents As Duplicates