Using dates with Cassandra - datetime

I've just started my adventure with Cassandra database. I've managed to learn some basics but what I still can't understand is how to work with dates in Cassandra?
So for example in MySQL we have a datetime type for a field and we can query (for example) all fields with creation date less then 2010-01-01. Furthermore we can order the result by creation date field.
How can we achieve the same with Cassandra? How to define the corresponding Column Family and how to query (CQL) it to get the same result?

You can use type DateType to define a column of type DateType in your column family. You should really read this page, it has description and example how to do range query (that is creationdate < 2010-01-01). For ordering, you can refer to the SliceRange but this will probably cover in the cassandra client already. You will probably want to look into the cassandra client to do the query.
This is a snippet on how to do query in cassandra using hector client.
// 2010-01-01
Date date = new Date(1262275200L);
try
{
getConnection();
IndexedSlicesQuery<String, String, String> indexedSlicesQuery = HFactory.createIndexedSlicesQuery(keyspace, ss, ss, ss);
indexedSlicesQuery.setColumnNames("name");
indexedSlicesQuery.addLtExpression("timestamp", ByteBufferUtil.string(date_s.toByteBuffer(date)));
indexedSlicesQuery.addEqualsExpression("searchall", ByteBufferUtil.string(bs.toByteBuffer(true)));
indexedSlicesQuery.setColumnFamily(column_family);
indexedSlicesQuery.setStartKey("");
System.out.println(indexedSlicesQuery.toString());
QueryResult<OrderedRows<String, String, String>> res = indexedSlicesQuery.execute();
List<Row<String, String, String>> list = res.get().getList();
for (Row<?, ?, ?> row : list)
{
System.out.println(row.getKey());
}
}

Related

When to use Map and SqlParameterSource in namedParameterJdbcTemplate?

String SQL = "INSERT INTO Employee (name, age, salary) VALUES (:name,:age,:salary)";
Map namedParameters = new HashMap();
namedParameters.put("name", name);
namedParameters.put("age", age);
namedParameters.put("salary", salary);
namedParameterJdbcTemplate.update(SQL, namedParameters);
String SQL = "UPDATE Employee SET age = :age WHERE empid = :empid";
SqlParameterSource namedParameters = new MapSqlParameterSource();
namedParameters.addValue("age", age);
namedParameters.addValue("empid", empid);
namedParameterJdbcTemplate.update(SQL, namedParameters);
Seems both Map and SqlParameterSource are same. But why did API developers added these API's ? Is there any particular scenario to use Map or SqlParameterSource which makes execution faster? Please explain me clearly. Thanks in advance.
Using a Map is fine for simple cases, but there are two benefits to using SqlParamaterSource over a Map.
The first is simply the builder pattern allowing you to add multiple values inline (namedParameters.addValue().addValue().addValue() etc).
The second is more powerful. The jdbcTemplate will auto-determine the sqlType of your map values while the SqlParamaterSource allows you to explicitly use the sqlType of your choice. This can be an issue depending on your database, indexes and parameters.
An example would be Integers and Longs with an Oracle database. The jdbc template will add these objects to your query with surrounding quotes '' making them effectively strings in your database query. If you have a number in your database with leading 0's it will not be found because '0XXXX' will not match 'XXXX'. If you pass in the right sqlType, the jdbc template will do a number comparison without quotes so XXXX will equal XXXX.
When my place holder values were of different datatypes, this (MapSqlParameterSource) really helped me:
String SQL = "UPDATE Employee SET joindate = :joinDate WHERE empid = :empid";
MapSqlParameterSource namedParameters = new MapSqlParameterSource();
namedParameters.addValue("date", joinDate, Types.Date);
namedParameters.addValue("empid", empid, Types.Integer);
namedParameterJdbcTemplate.update(SQL, namedParameters);

Capture only month and year (or null) - then convert that to a date

I'm currently working with a client that has a VB.NET web application that was developed internally. They've got everything storing to an Access database which they cannot alter or change for their own reasons. I'm not familiar with any of these technologies, so I'm hoping you may have a solution.
The client has a date field that they are only capturing mm/yyyy or blank. They need this information to save to a datetime field in the database. I'm trying to work up a statement that will automatically take the date entered and convert from mm/yyyy to mm/01/yyyy if the date is provided, or 01/01/1970 if the field was left blank. Can anyone assist?
If we are talking about MS Access functions DateSerial is what you are looking for. The basic syntax is below. If the stored value is text you will need to use the Mid function to parse the text into the year and month and you can use use a hard coded 1 for the day.
DateSerial ( year, month, day )
This function can be used in a select or update. Additional logic will be required to provide a default value for the blank result. Typically in Access this type of logic is done with an IIF.
You can use a combination of the IIf,IsNull and CDate functions, like so:
IIf(IsNull([YourDateFField]),#1/1/1970#,CDate([YourDateFField]))
This tests if your field is null and if yes it returns 1/1/1970, if no it will convert your date string to an actual date (e.g. CDate("04/2014") will return 4/1/2014)
This (MSAccess/VBA) function will do what you are asking. If you pass-in a string like mm/yyyy, it will return a datetime like mm/01/yyyy. However, if the string does not fit that pattern (or equiv), the function will return a date time of 1/1/1970, like you asked.
'in MSAccess:
Public Function mmyyyyToDate(mmyyyy As String) As Datetime
If IsDate(Replace(mmyyyy, "/", "/01/")) Then
Return CDate(Replace(mmyyyy, "/", "/01/"))
Else
Return #1/1/1970#
End If
End Function
It would be more efficient to run it in MSAccess, but if you want to run it in VB.net instead, the syntax is different:
'in VB.NET
Public Function mmyyyyToDate(mmyyyy As Object, Optional defaultDate As DateTime = "1/1/1970") As DateTime
Dim re As DateTime
If Convert.IsDbNull(mmyyyy)
return defaultDate
ElseIf DateTime.TryParse(Replace(mmyyyy, "/", "/01/"), re) Then
Return re
Else
Return defaultDate
End If
End Function
Example of running it:
'MSAccess query syntax
INSERT INTO NewDateTable (NewDateColumn)
SELECT mmyyyyToDate(oldColumn) FROM OldTable
If you can't add a new function to the MSAccess DB, you could turn this function into an inline statement (by using an IIF), but it looks pretty ugly:
'MSAccess query syntax
INSERT INTO NewDateTable (NewDateColumn)
SELECT IIF(IsDate(Replace(oldColumn, "/", "/01/")), Replace(mmyyyy, "/", "/01/"), #1/1/1970#)
FROM OldTable

nature of SELECT query in MVC and LINQ TO SQL

i am bit confused by the nature and working of query , I tried to access database which contains each name more than once having same EMPid so when i accessed it in my DROP DOWN LIST then same repetition was in there too so i tried to remove repetition by putting DISTINCT in query but that didn't work but later i modified it another way and that worked but WHY THAT WORKED, I DON'T UNDERSTAND ?
QUERY THAT DIDN'T WORK
var names = (from n in DataContext.EmployeeAtds select n).Distinct();
QUERY THAT WORKED of which i don't know how ?
var names = (from n in DataContext.EmployeeAtds select new {n.EmplID, n.EmplName}).Distinct();
why 2nd worked exactly like i wanted (picking each name 1 time)
i'm using mvc 3 and linq to sql and i am newbie.
Both queries are different. I am explaining you both query in SQL that will help you in understanding both queries.
Your first query is:
var names = (from n in DataContext.EmployeeAtds select n).Distinct();
SQL:-
SELECT DISTINCT [t0].[EmplID], [t0].[EmplName], [t0].[Dept]
FROM [EmployeeAtd] AS [t0]
Your second query is:
(from n in EmployeeAtds select new {n.EmplID, n.EmplName}).Distinct()
SQL:-
SELECT DISTINCT [t0].[EmplID], [t0].[EmplName] FROM [EmployeeAtd] AS
[t0]
Now you can see SQL query for both queries. First query is showing that you are implementing Distinct on all columns of table but in second query you are implementing distinct only on required columns so it is giving you desired result.
As per Scott Allen's Explanation
var names = (from n in DataContext.EmployeeAtds select n).Distinct();
The docs for Distinct are clear – the method uses the default equality comparer to test for equality, and the default comparer sees 4 distinct object references. One way to get around this would be to use the overloaded version of Distinct that accepts a custom IEqualityComparer.
var names = (from n in DataContext.EmployeeAtds select new {n.EmplID, n.EmplName}).Distinct();
Turns out the C# compiler overrides Equals and GetHashCode for anonymous types. The implementation of the two overridden methods uses all the public properties on the type to compute an object's hash code and test for equality. If two objects of the same anonymous type have all the same values for their properties – the objects are equal. This is a safe strategy since anonymously typed objects are essentially immutable (all the properties are read-only).
Try this:
var names = DataContext.EmployeeAtds.Select(x => x.EmplName).Distinct().ToList();
Update:
var names = DataContext.EmployeeAtds
.GroupBy(x => x.EmplID)
.Select(g => new { EmplID = g.Key, EmplName = g.FirstOrDefault().EmplName })
.ToList();

Compare local DateTime to DateTimeOffset

I have a database with a DateTime column, and want to compare it to some DateTimeOffset. The DateTime column is in (server) local time. There is nothing I can do about that apart from rant about the WTF'yness of it, which I like to do frequently and vehemently, so I can skip it here for now.
I'd like to be able to select all rows from the table where DateTime x happens before my DateTimeOffset. I can live with assuming that if it is DST on the server now, the DateTime column is also in DST and the other way around. These times will be localised around 'now', with the DateTime (almost) always being in the past few hours. I'll take the DST change on the chin when it happens, but the solution shouldn't be always wrong in either DST or non-DST.
As a bonus requirement, the table is large, so performing any manipulation on the DateTime is out of the question. What it comes down to I suppose is I'm looking for the equivalent of
DECLARE #dto datetimeoffset(4) = '12-10-25 12:32:10 +06:00';
DECLARE #dt datetime = --this is where the magic happens?
SELECT * FROM MyTable WHERE datetimecol < #dt
could anyone help me making the magic happen?
You'll need a SQL CLR function to do this. Inspired by this post, I wrote the following:
using System;
using Microsoft.SqlServer.Server;
public class UserDefinedFunctions
{
[SqlFunction(IsDeterministic = false)]
public static DateTime? ConvertDateTimeOffsetToLocalDateTime(DateTimeOffset? dto)
{
if (!dto.HasValue)
return null;
return dto.Value.ToLocalTime().DateTime;
}
}
You can compile this yourself if you like, or just deploy it using the following, which contains the serialized binary and SQL deployment script:
EXEC sp_configure 'clr enabled', 1;
GO
RECONFIGURE
GO
CREATE ASSEMBLY [SqlClrDateTime]
FROM 0x4D5A90000300000004000000FFFF0000B800000000000000400000000000000000000000000000000000000000000000000000000000000000000000800000000E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F742062652072756E20696E20444F53206D6F64652E0D0D0A2400000000000000504500004C0103004F68E4520000000000000000E00002210B010B00000800000006000000000000EE260000002000000040000000000010002000000002000004000000000000000400000000000000008000000002000000000000030040850000100000100000000010000010000000000000100000000000000000000000942600005700000000400000C002000000000000000000000000000000000000006000000C0000005C2500001C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000080000000000000000000000082000004800000000000000000000002E74657874000000F4060000002000000008000000020000000000000000000000000000200000602E72737263000000C00200000040000000040000000A0000000000000000000000000000400000402E72656C6F6300000C0000000060000000020000000E00000000000000000000000000004000004200000000000000000000000000000000D026000000000000480000000200050094200000C804000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001330010030000000010000110F00280600000A2D0A1200FE150200001B062A0F00280700000A0B1201280800000A0C1202280900000A730A00000A2A1E02280B00000A2A42534A4201000100000000000C00000076342E302E33303331390000000005006C00000070010000237E0000DC010000E001000023537472696E677300000000BC0300000800000023555300C4030000100000002347554944000000D4030000F400000023426C6F620000000000000002000001471502080900000000FA253300160000010000000A0000000200000002000000010000000B000000050000000100000002000000010000000200000000000A00010000000000060042003B00060049003B00060054003B0006005D003B000600B5009B000600E100CE001B00F50000000600240104010600440104010A0098017D010000000001000000000001000100010010001D00000005000100010050200000000096006C000A0001008C20000000008618910019000200000001009700290091001D003100910022004100910028004900910019005100910019000C00AD014C000C00BA0157002100C4015C002100D001610014009100660009009100190020002B002D002E001300C1002E000B0079002E001B00CA002E002300D3006C0045005000048000000000000000000000000000000000620100000400000000000000000000000100320000000000040000000000000000000000010071010000000000000000003C4D6F64756C653E0053716C436C724461746554696D652E646C6C0055736572446566696E656446756E6374696F6E73006D73636F726C69620053797374656D004F626A656374004E756C6C61626C656031004461746554696D65004461746554696D654F666673657400436F6E766572744461746554696D654F6666736574546F4C6F63616C4461746554696D65002E63746F720064746F0053797374656D2E52756E74696D652E56657273696F6E696E67005461726765744672616D65776F726B4174747269627574650053797374656D2E446961676E6F73746963730044656275676761626C6541747472696275746500446562756767696E674D6F6465730053797374656D2E52756E74696D652E436F6D70696C6572536572766963657300436F6D70696C6174696F6E52656C61786174696F6E734174747269627574650052756E74696D65436F6D7061746962696C6974794174747269627574650053716C436C724461746554696D650053797374656D2E44617461004D6963726F736F66742E53716C5365727665722E5365727665720053716C46756E6374696F6E417474726962757465006765745F48617356616C7565006765745F56616C756500546F4C6F63616C54696D65006765745F4461746554696D650000000000032000000000004BEC2CC7757F1E49B9400968748F57020008B77A5C561934E0890E000115110901110D15110901111103200001042001010E05200101111D0420010108170100010054020F497344657465726D696E69737469630006151109011111032000020615110901110D04200013000420001111042000110D0520010113000C070315110901110D111111114701001A2E4E45544672616D65776F726B2C56657273696F6E3D76342E300100540E144672616D65776F726B446973706C61794E616D65102E4E4554204672616D65776F726B20340801000200000000000801000800000000001E01000100540216577261704E6F6E457863657074696F6E5468726F7773010000000000004F68E45200000000020000001C010000782500007807000052534453DABD35B6971B914293249E1EC9335A4E01000000633A5C4465765C53716C436C724461746554696D655C53716C436C724461746554696D655C6F626A5C52656C656173655C53716C436C724461746554696D652E70646200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000BC2600000000000000000000DE260000002000000000000000000000000000000000000000000000D02600000000000000000000000000000000000000005F436F72446C6C4D61696E006D73636F7265652E646C6C0000000000FF25002000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100100000001800008000000000000000000000000000000100010000003000008000000000000000000000000000000100000000004800000058400000640200000000000000000000640234000000560053005F00560045005200530049004F004E005F0049004E0046004F0000000000BD04EFFE00000100000000000000000000000000000000003F000000000000000400000002000000000000000000000000000000440000000100560061007200460069006C00650049006E0066006F00000000002400040000005400720061006E0073006C006100740069006F006E00000000000000B004C4010000010053007400720069006E006700460069006C00650049006E0066006F000000A001000001003000300030003000300034006200300000002C0002000100460069006C0065004400650073006300720069007000740069006F006E000000000020000000300008000100460069006C006500560065007200730069006F006E000000000030002E0030002E0030002E003000000048001300010049006E007400650072006E0061006C004E0061006D0065000000530071006C0043006C0072004400610074006500540069006D0065002E0064006C006C00000000002800020001004C006500670061006C0043006F0070007900720069006700680074000000200000005000130001004F0072006900670069006E0061006C00460069006C0065006E0061006D0065000000530071006C0043006C0072004400610074006500540069006D0065002E0064006C006C0000000000340008000100500072006F006400750063007400560065007200730069006F006E00000030002E0030002E0030002E003000000038000800010041007300730065006D0062006C0079002000560065007200730069006F006E00000030002E0030002E0030002E0030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000C000000F03600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
WITH PERMISSION_SET = SAFE
GO
CREATE FUNCTION dbo.ConvertDateTimeOffsetToLocalDateTime(#dto datetimeoffset)
RETURNS datetime2
AS EXTERNAL NAME SqlClrDateTime.UserDefinedFunctions.ConvertDateTimeOffsetToLocalDateTime
GO
And here is how you can use it in your scenario:
DECLARE #dto datetimeoffset(4) = '12-10-25 12:32:10 +06:00'
DECLARE #dt datetime = dbo.ConvertDateTimeOffsetToLocalDateTime(#dto)
SELECT * FROM MyTable WHERE datetimecol < #dt

Inserting current date and time in SQLite database

I want to create a table in SQLite in which one of the field is for date, in which date and time of current instance should save. Which data type should I use?
I'm planning to use 'timestamp'. How to insert current timestamp value to the field? Also how to write content values for this date field?
SQLite supports the standard SQL variables CURRENT_DATE, CURRENT_TIME, and CURRENT_TIMESTAMP:
INSERT INTO Date (LastModifiedTime) VALUES(CURRENT_TIMESTAMP)
The default data type for dates/times in SQLite is TEXT.
ContentValues do not allow to use generic SQL expressions, only fixed values, so you have to read the current time in Java:
cv.put("LastModifiedTime",
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
INSERT INTO Date (LastModifiedTime) VALUES(DateTime('now'))
Use this site for further reference.
To get the current local(system) time, add the 'localtime' option:
select datetime('now', 'localtime');
I'm using timestamps a lot in my app. For me the best way to keep the timestamp is to convert it in milliseconds. After that it is easy to convert it to any locale.
If you need the current time use System.currentTimeMillis().
Content values are easy to use, you just and field and value, like:
ContentValues ins_reminder = new ContentValues();
ins_reminder.put("REMIND_TIMESTAMP", System.currentTimeMillis());
Since SQLite 3.38.0, there is a unixepoch() function that returns UNIX timestamp in integer. Does the same thing as strftime('%s').
References:
release log draft
check-in
In my case i wanted to have a timestamp with fractions of a second.
The keyword CURRENT_TIMESTAMP has only a precision of YYYY-MM-DD HH:MM:SS (see docs DEFAULT clause).
The function strftime() can return fractions of a second
Example to use strftime() in an INSERT
INSERT INTO YourTable (TimeStamp)
VALUES (strftime('%Y-%m-%d %H:%M:%S:%s'))
Comparison of CURRENT_TIMESTAMP and strftime()
SELECT 'CURRENT_TIMESTAMP' as Timestamp_Command,
CURRENT_TIMESTAMP as TimeStamp_Precision,
'only seconds' as Timestamp_Comment
UNION ALL
SELECT 'strftime(%Y-%m-%d %H:%M:%S:%s)' as Timestamp_Command,
(strftime('%Y-%m-%d %H:%M:%S:%s')) as TimeStamp_Precision,
'with fraction of a second' as Timestamp_Comment
Example to use it in c#
The following is based on bulk insert in sqlite with ado.net
public static void InsertBulk(SqliteConnection connection)
{
connection.Open();
using (var transaction = connection.BeginTransaction())
{
var command = connection.CreateCommand();
command.CommandText =
#"INSERT INTO BulkInsertTable (CreatedOn, TimeStamp)
VALUES ($createdOn, strftime('%Y-%m-%d %H:%M:%S:%s'))";
var parameter3 = command.CreateParameter();
parameter3.ParameterName = "$createdOn";
command.Parameters.Add(parameter3);
// Insert a lot of data
// calling System.DateTime.Now outside the loop is faster
var universalTime = System.DateTime.Now.ToUniversalTime();
for (var i = 0; i < 15_000; i++)
{
parameter3.Value = System.DateTime.Now.ToUniversalTime();
// faster
// parameter3.Value = universalTime;
command.ExecuteNonQuery();
}
transaction.Commit();
}
connection.Close();
}

Resources