How to have a database counter that resets monthly? - sql

I have an application that needs to generate an unique identifier per item, this identifier is a mix of some initials, the date and 4 digits that increment for each new item. The tricky part is that the last 4 digits should reset monthly.
As an example, lets say we have UID "SP-20121218-0001", the last 4 digits "0001" will increment up until January, and then the first item created in January should have "SP-20130101-0001".
Any thoughts?

create a table with fields Year, Month, CurrentCount. write a stored procedure that selects a row for the current year and month, if it does not exists creates it and increments the number.

To me this sounds like the perfect use case for a stored function.
In postgresql you would do this by having a sequence and then using a function to select a value from the sequence in combination with working out the current date and when the date turned over, resetting the sequence.
The best way though would be to not bother resetting the sequence and to just go with a unique number supplemented by the date.

One possible option is to base the last 4 digits on a database sequence and then have a separate process that will reset that database sequence when a new month starts.

Related

How to create a calculated column with unique values ​for every field

I'm currently facing a problem working with a CV on SAP HANA.
Basically my goal is to create a calculated field on every row, based on the content of another field of the same row.
More specifically, I have a column of dates with the current format (YYYYMMDD) and I have to automatically create an associated field based on current criterias:
the date with the current month and year has to be associated with 0;
every month after the current one, has to be, in order, increased by one (example: for 20220930 I have 0, for 20221030 I have 1, for 20221230 I have 3.. for 20231230 I have 15, this until 600);
if more than one row has the same date, the calculated field has to be the same, that means that, for example, if more than one row has 20221030, I need to have 1 on all of them).
My first idea was to use a rank node, but the outcome is not as I expected.
Attached, there is a screenshot of a data preview of my attempt (just showing the dates and rank_field columns..).
Any advice is welcome, thanks.
Example of data

Calculate averages of previous 7 rows SQL

Consider the following result set returned from a stored procedure:
The goal with the IHD column, is to do a calculation of the previous 6 rows (days) to determine a IHD value from within the stored procedure.
In this case, only from row 7 and onwards will there be an IHD value, since the calculation needs to take into consideration the previous 6 days' closing balance including current day (day 7) and calculate an average. Basically, it needs to use row 1 to 7 for row's 7 IHD value. And then, to calculate row 8's IHD value, it needs to use row 2 to 8.
I have had a look at SQL LAG function, but this only allows me to skip to 1 previous row, and I am not quite sure if I would be able to successfully use the LAG function in a self referencing CTE where averages of more than one previous row is required.
How should I approach this scenario?
Use ROWS BETWEEN. Without Consumable sample data and expected results I can only give Pseudo SQL, but this'll put you on the right path:
AVG({Your Column}) OVER ([PARTITION BY {Other Column}] ORDER BY {Column To Order BY}
ROWS BETWEEN 6 PRECEDING AND CURRENT ROW)
Obviously replace the parts in braces ({}) and remove the parts in brackets ([]) if not required.

Store date range in a single column in Oracle SQL

Here trip 1 involves 2 activity_code in a single day and also concludes in a single day and most other activities are just single day but i have one trip that span over more than one day.
What could be the best possible way to store date range for that column that span more than one days.
Splitting the column into multiple begin date and end date just doesn't make sense as there would be many blank columns?
trip_id(pk,fk) Activity_code(pk,fk) date
1 a1 1st October 2015
1 a2 1st October 2015
2 a3 2nd -5th October 2015
Keep in mind that i need to search the activity_code on basis of month. such as list all the activity code that occur in October ?
Is it possible to insert a range of date in a single column or any other design solution ?
Is there any datatype that can represent the date range in single value ?
PS: oracle 11g e
Store the date ranges as FirstDate/LastDate or FirstDate/Duration.
This allows you to store the values in the native format for dates. Storing dates as strings is a bad, bad idea, because strings don't have all the built-in functionality provided for native date types.
Don't worry about the additional storage for a second date or duration. In fact, the two columns together are probably smaller than storing the value as a string.
Splitting the date into start date and end date would be ideal. Storing dates as strings is not recommended. If you store your dates as strings then there is a possibility of malformed data being stored in the column since a VARCHAR2 column will allow any value. You will have to build strong validations in your script while inserting the data which is unnecessary.
Secondly, you will not be able to perform simple operations like calculating the duration/length of the trip easily if both the start_date and end_date are stored in the same column. If they are stored in different columns it would be as simple as
SELECT trip_id, activity_code, end_date - start_date FROM trips;

How can I generate an ID that will reset every year?

I need help in VB.net I'm a newbie in programming.
I have a problem in generating an ID with the format
`yyyy` = now.year
`mm` = now.month
`0000` = auto number
I want to increment the auto number everytime I add records
so it goes like this
2014090001
and also it will reset back to 0000 when year changes.
thank you for all your replies, I took all your advice and I got a solution CONSIDER THIS THREAD AS CLOSE!!
my final solution is creating another table in database with the fields ID, counter, and YEAR
I created a condition that will test the current year, so if the year = now.year the counter will just increment by 1 and if year <> to now.year then the counter will back to 0. it will add up another records in that table so the use of ID is to delete the previous records.

Is it possible to return part of a field from the last row entered into a table

I am proposing to have a table (the design isn't settled on yet and can be altered dependent upon the views expressed in reply to this question) that will have a primary key of type int (using auto increment) and a field (ReturnPeriod of type Nchar) that will contain data in the form of '06 2013' (representing in this instance June 2013).
I would simply like to return 06 or whatever happens to be in the last record entered in the table. This table will never grow by more than 4 records per annum (so it will never be that big). It also has a column indicating the date that the last entry was created.
That column seems to my mind at least to be the most suitable candidate for getting the last record, so essentially I'd like to know if sql has a inbuilt function for comparing the date the query is run to the nearest match in a column, and to return the first two characters of a field.
So far I have:
Select Mid(ReturnPeriod,1,2) from Returns
Where DateReturnEntered = <and this is where I'm stuck>
What I'm looking for is a where clause that would get me the last entered record using the date the query is run as its reference point(DateRetunEntered of type Date contains the date a record was entered).
Of course there may be an even easier way to guarantee that one has the last record in which case I'm open to suggestions.
Thanks
I think you should store ReturnPeriod as a datetime for example not 06 2013 as a VARCHAR but 01.06.2013 as a DATETIME (first day of 06.2013).
In this case, if I've got your question right, you can use GETDATE() to get current time:
SELECT TOP 1 MONTH(ReturnPeriod)
FROM Returns
WHERE DateReturnEntered<=GETDATE()
ORDER BY DateReturnEntered DESC
If you store ReturnPeriod as a varchar then
SELECT TOP 1 LEFT(ReturnPeriod,2)
FROM Returns
WHERE DateReturnEntered<=GETDATE()
ORDER BY DateReturnEntered DESC
I would store your ReturnPeriod as a date datatype, using a nominal 1st of the month, e.g. 1 Jun 2013, if you don't have the actual date.
This will allow direct comparison against your entered date, with trivial formatting of the return value if required.
Your query would then find the latest date prior to your date entered.
SELECT MONTH(MAX(ReturnPeriod)) AS ReturnMonth
FROM Returns
WHERE ReturnPeriod <= #DateReturnEntered