Using text in a column of Date/Time type in access - database

I have a column in MS Access in which the data could be any of the following:
A date
Text string: "n/a"
Text string: "n/e"
The vast majority of entries will be dates but a very few will need to be these specified text strings. I would like to still be able to perform date calculations on the column. Whats the best datatype to use?

In my opinion the best approach would be to leave the date field as Date/Time and then add another field to indicate the status if the Date/Time field is Null. Something like:
DateField DateStatus
--------- ----------
2014-09-21
n/a
2014-09-23
2014-09-25
n/e
You could use a single Text field, but then any time you wanted to use the field value as a proper Date/Time value you'd have to convert it using CDate(). You would also have the possibility of other junk getting in there, or dates getting entered in different formats (e.g. d/m/yyyy vs. m/d/yyyy). And finally, you would lose the ability to easily determine whether a Date/Time value is in a particular row (which in my approach would simply be ... WHERE DateField IS [NOT] NULL).

I agree with Gord Thompson's answer - mainly because it's so non-intuitive to have, essentially, two completely different types of data in a single column, and because it's going to make validation/data integrity stuff so much harder with little upside - and, as he indicates with the CDate() reference, dates basically only work reliably like dates if they're in a "date/time" field. Microsoft has a page on choosing a data type that explains some of the Access-specific differences in more detail.
I also suggest that you don't actually have a text field for those "comments," since you say there's only a handful of potential options - use a Long Integer and connect back to a separate table with the list of allowable entries. This will allow you to run reports more easily, change the "display text" in one step instead of potentially dozens of times, etc. It also saves a relatively small amount of space per record (long integer = 4 bytes; text = up to 255 bytes.)
You can also do fun data/reporting stuff with that Comment (long integer) field and dates - even combined into ranges, by the way - queries let you use the two different columns to create a single answer. I have a report that's grouped so that you can see stats for everything that's active (by quarter in which they start) plus everything that's pending (with the code indicating who's responsible for watching this record,) plus everything that's not pending but still doesn't have a start date (with the reason code displayed,) plus everything that's expired (by quarter in which they ended.) It looks like each of those things is in a single column in the report, but it's actually like five columns that have been concatenated with the IIf function.
(Almost every argument I can come up with boils down to "this is what relational databases are all about and why they're so awesome.)

Related

SQL Server Problem with carriage splitting a string

DECLARE #Description2 VARCHAR(MAX);
SELECT #Description2 = '1. Each week there will be a philosophical question to address. For example, you will address questions such as do we have freewill or are we determined?, what does quantum physics tell us about the nature of reality?, and what are the philosophical implications of Darwinian evolution? Utilizing the readings for the week prepare a written essay response. There will be a minimum of ten mini-essays for the term and each must be a minimum of 200 words.
2. Develop an argument on the topic of ontology, focusing specifically on the question "Are we just the brain?" Argue either the materialist position (we are just the brain) or the non-materialist position (we are not just the brain), drawing from the primary writings of the philosophers. Be sure to explain both positions in your essay and then make the case for the position you are supporting. This argumentative essay needs to be at least 750 words in length. We will then conduct an in class debate and you will need to argue your point in a debate setting.
3. Develop an argument in the area of ethics, arguing for or against animal rights. Make sure to utilize primary writings in the construction of your argument. This argumentative essay needs to be at least 750 words in length. Students will present their position to the class in a ten minute oral presentation.
4. Having read the writings of Epictetus and Sartre compare and contrast Stoicism and Existentialism. Write a 750 word essay highlighting the key differences and similarities.
5. Analyze the primary readings of Nietzsche in journal form. Choose 10 separate passages to analyze and include the following: a) a summary of the passage; b) an interpretation or analysis of the argument; c) a comparison and/or contrast to the ideas of another philosopher or philosophy; d) personal insight into the writing by applying the ideas to you or to the world at large (its meaning on a deeper, more personal level). This journal will be at least 1000 words in length. '
set #Description2 = replace(replace(replace(replace(replace(replace(replace(#Description2,'<p>',''),'</p>',''),'<br />',''),' ',''),'<br />.<br />',''),'<div>',''),'</div>','')
set #Description2 = concat('???',REPLACE(#Description2,CHAR(13)+char(10),'???'))
select ltrim(s.Item)
from dbo.DelimitedSplit8K_LEAD(#Description2, '???') s
where ltrim(s.Item) <> ''
So what do you actually want to happen? And what are you seeing that is different from what you want?
In SSMS, if you go to tools > options > query results > SQL Server > results to grid, there is a checkbox labelled "retain CR/LF on copy or save" which determines how varchar data will be treated when you click on the output grid results and copy the data.
If you check the checkbox, the carriage return/linefeed will be retained. Ie, if you do:
select 'a
b'
Run that query, copy the result from the grid, and paste it into, say, notepad, you will get 2 lines of text in notepad.
On the other hand, if you don't check the checkbox, you will only get a single line in notepad.
Be aware that if you change the setting of this checkbox, I believe you will need to open a new query window to see the new behaviour.
Note that this only controls the behaviour of SSMS. It has nothing to do with how your data is "really" stored, for example, if you insert it into a table. If you have an application reading data from a table, the way it formats the output is up to the application.

Possible record collisions due to the size / definition of the TIMESTAMP field in the TIME SERIES type containers of GridDB

I am working with GridDB and I have observed loss of records during the insertions that I attribute to the lack of definition of the timestamp field.
I tried to give more definition in the entry field but saving it makes it trim. Logs do not indicate any data loss or erroneous writing.
A query DB:
[{
"columns":[
{"name":"original_timestamp","type":"TIMESTAMP"},
{"name":"FIELD_A","type":"STRING"}
...
{"name":"FIELD_Z","type":"STRING"}
{"name":"code_timestamp","type":"STRING"}],
"results":[
"2019-07-19T11:28:42.328Z",
"SOME String Value for A",
...
"SOME String Value for Z",
"2019-07-19 11:28:59.239922"}
]
The number of registered ingested its lower than expected.
We're working on a model based on two indexes. Any other idea and / or helpful experience?
Thanks in advance!
GridDB stores TIMESTAMP values in millisecond resolution, inserting records with greater resolution such as micro or nanosecond resolution will result in the timestamp value being truncated.
There are three ways to get around the timestamp collisions:
Use a Collection with a long as your first index. In that long, store a Unix Epoch in micro or nanoseconds as required. You will obviously lose some time series functions and have to manually convert comparison operators to a Unix epoch in your desired resolution.
Use a collection and disable the row key (No #RowKey tag in Java or set the last Boolean in ContainerInfo to False in other languages). This will allow multiple records to have the same "row key value". You can enable a secondary index on this column to ensure queries are still fast. TIMESTAMP and TO_TIMESTAMP_MS functions still work but I'm fairly certain none of the other special timestamp functions will work. When I've had to deal with Timestamp collisions in GridDB, this is the solution I chose.
Detect the collisions before you insert and if there is going to be a collision, write the colliding record into a separate container. Use multi-get/query to query all of the containers.

SQL Server validating postcodes

I have a table containing postcodes but there is no validation built in to the entry form so there is no consistency in the way they are stored in the database, sample below:
ID Postcode
001742 B5
001745
001746
001748 DY3
001750
001751
001768 B276LL
001774 B339HY
001776 B339QY
001780 WR51DD
I want to use these postcode to map the distance from a central point but before I can do that I need to put them into a valid format and filter out any blanks or incomplete postcodes.
I had considered using
left(postcode,3) + ' ' + right(postcode,3)
To correct the formatting but this wouldn't work for postcodes like 'M6 8HD'
My aim is to get the list of postcodes in a valid format but I don't know how to account for different lengths of postcode. Is this there a way to do this in SQL Server?
As discussed in the comments, sometimes looking at a problem the other way around presents a far simpler solution.
You have a list of arbitrary input provided by users, which frequently doesn't contain the correct spacing. You also have a list of valid postcodes which are correctly spaced.
You're trying to solve the problem of finding the correct place to insert spaces into your arbitrary inputs to make them match the list of valid codes, and this is extremely difficult to do in practice.
However, performing the opposite task - removing the spaces from the valid postcodes - is remarkably easy to do. So that is what I'd suggest doing.
In our most recent round of data modelling, we have modelled addresses with two postcode columns - PostCode containing the postcode as provided from whatever sources, and PostCodeNoSpace, a computed column which strips whitespace characters from PostCode. We use the latter column for e.g. searches based on user input. You may want to do something similar with your list of Valid postcodes, if you're keeping it around permanently - so that you can perform easy matches/lookups and then translate those matches back into a version that has spaces - which is actually a solution to the original question posed!

Remove Duplicate adjacent Sub-String from String in Microsoft SQL Server

I am using SQL Server 2008 and I have a column in a table, which has values like below. It basically shows departure and arrival information.
-->Heathrow/Dublin*Dublin/Heathrow
-->Gatwick/Liverpool*Liverpool/Carlisle *Carlisle/Gatwick
-->Heathrow/Dublin*Liverpool/Heathrow
(The 3rd example shown above is slightly different where the person did not depart from Dublin, instead departed from a Liverpool).
This makes the column too lengthy, and I want to remove only the adjacent duplicates, so the information can be shown like below:
-->Heathrow/Dublin/Heathrow
-->Gatwick/Liverpool/Carlisle/Gatwick
-->Heathrow/Dublin***Liverpool/Heathrow
So, this would still show the correct travel route, but omits only the contiguous duplicates. Also, in the 3rd case, since the departure and arrival information location is not the same, Iwould like to show it as ***.
I found a post here that removes all duplicates (Find and Remove Repeated Substrings) but this is slightly different from the solution that I need.
Could someone share any thoughts please?
The first step is to adapt the process defined in the following link so that it splits based on /:
T-SQL split string
This returns a table which you would then loop through checking if the value contains an *. In that case you would get the text values before and after the * and compare them. Use CHARINDEX to get the position of the *, and SUBSTRING to get the values before and after. Once you have those check both values and append to your output string accordingly.
So you have a database column that contains this text string? Is your concern to display the data to the user in a new format, or to update the data in your database table with a new value?
Do you have access to the original data from which this text string was built? It would probably be easier to re-create the string in the format you desire than it would be to edit the existing string programmatically.
If you don't have access to this data, it would probably be a lot simpler to update your data (or reformat it for display) if you do the string manipulation in a high-level language such as c# or java.
If you're reformatting it for display, write the string manipulation code in whatever language is appropriate, right before displaying it. If you're updating your table, you could write a program to process the table, reading each record, building the replacement string, and updating the record before moving on to the next one.
The bottom line is that T-SQL is just not a good language for doing this sort of string examination and manipulation. If you can build a fresh string from the original data, or do your manipulation in a high-level language, you'll have an easier job of it and end up with more maintainable code.
I wrote a code for the first example you gave. You still need to
improve it for the rest ...
DECLARE #STR VARCHAR(50)='Heathrow/Dublin*Dublin/Heathrow'
IF (SELECT SUBSTRING(#STR,CHARINDEX('/',#STR)+1,CHARINDEX('*',#STR)-CHARINDEX('/',#STR)-1)) =
(SELECT SUBSTRING(#STR,CHARINDEX('*',#STR)+1,LEN(SUBSTRING(#STR,CHARINDEX('/',#STR)+1,CHARINDEX('*',#STR)-CHARINDEX('/',#STR)-1))))
BEGIN
SELECT STUFF(#STR,CHARINDEX('*',#STR),LEN(SUBSTRING(#STR,CHARINDEX('/',#STR)+1,CHARINDEX('*',#STR)-CHARINDEX('/',#STR)-1))+1,'')
END
ELSE
BEGIN
SELECT STUFF(#STR,CHARINDEX('*',#STR),LEN(SUBSTRING(#STR,CHARINDEX('*',#STR)+1,LEN(SUBSTRING(#STR,CHARINDEX('/',#STR)+1,CHARINDEX('*',#STR)-CHARINDEX('/',#STR)-1)))),'***')
END

store one date and two time fields

I need to store schedule date and times. Scheduale contains one date field and two time fields.
Is there any possibility to store schedule in one db field and not in two (datetime + datetime)?
I am using SQL Server 2005.
Thanks!
Whether it is "start"+"stop", or "start"+""duration", you have 2 pieces of information = store 2 pieces of information.
Using a string or XML makes no sense: this requires take more space, more processing, more code to search and use.
Why would you want to store what are effectively two datetimes in one field rather than two? Are there no cases where the schedule might have times that cross days? (ie. 01/03/2011 23:59, 02/03/2011 01:35)? Do you not mind having to parse out the information rather than having it immediately ready for query?
If you really want to, there's no reason you can't store it as a string type, comma separated possibly, maybe XML as suggested, but I can't say it's recommended as date/time fields are more space efficient, nice and fast/flexible for searching purposes, and there are many useful T-SQL functions which can easily be used on date/time types which you'd be hard pushed to use on a string without some parsing and casting/converting.
If you can come up with a good reason for not using two datetime fields, I'll have another Donut! (ps. happy Fat Thursday).
One quick, and horribly evil thought ... you could use part of the datetime to store the "difference" ... sneak it into the "seconds" and "milliseconds" values, and apply it to the main date/time to get the new value. A bit hacky, but it'd could do the job, depending on your range requirements.
-- Example: 01/03/2011 12:30:02
-- Translates into - first of March 2011, 12:30 to 14:30 (12:30 + (seconds * hours))
set #ModifiedDatetime =
DATEADD(hour, DATEPART(second, #originalDateTime), #originalDateTime);
Beware of rounding errors with milliseconds ... and please think about the consequences of what you're doing. God kills a kitten each time someone abuses a type :)
You can try using the XML field type and store an XML snippet in there, similar to the following:
<schedule date="2011-01-01" fromTime="12:00" toTime="14:00" />
You can then use XQuery in a select to transform the result set back to a "normal" row-based result set. A sample query implementing XQuery, based on my example's XML schema, could be as follows:
SELECT
[...]
, Schedule.value('(/schedule/#date)[1]','datetime') as [Date]
, Schedule.value('(/schedule/#fromTime)[1]','char(5)') as [FromTime]
, Schedule.value('(/schedule/#toTime)[1]','char(5)') as [ToTime]
FROM [TABLE]
I'm not saying that storing it as XML is the best way to do it (as the other answers rightfully state), but you asked IF it is possible and I propose a solution...

Resources