There are entries in a table containing 2 columns (integerdata, time). Time is stored in TEXT and is of format HH:MM, which is one of the standard format ( according to sqllite documentation). 'integerdata' is some integer. I am looking to obtain row contents grouped by hour of the day, with integerdata as AVG(integerdata) for each hour. Eg rows:
(10, 10:01)
(2, 10:25)
(5, 11:01)
(9, 11:25)
I wish to have the output like:
6, 10:00
7, 11:00
One novice and horrible way is to give a query for each hour range(making 24 queries). Something like:
SELECT AVG(integerdata) from table WHERE time BETWEEN 'time1' AND 'time2'
//time1 and time2 can vary between 10:00 to 11:00; then 11:00 to 12:00 ...
Second way might be to use GROUP BY Clause, but I am not sure how. I googled and also tried to look on some answers on stackoverflow but was of no help. I would really appreciate any contribution. Thanks!
I am looking to obtain row contents grouped by hour of the day, with
integerdata as AVG(integerdata) for each hour.
Here is my first idea. Since your time is still TEXT, you can use substr() function to get only hour from your time column and then you can use this substring in GROUP BY clause.
Select AVG(integerdata), SUBSTR(time, 0, 3) as gt from Table group by gt;
I assume that your time format is HH:MM so in this case SUBSTR(time, 0, 3) returns only hours and now you can start grouping by hours.
It returns: 10, 11, 12, ...
Related
In my database dates is stored in miliseconds as string. How to query unique dates considering only month and day and count how many date share same day?
Divide by 1000 to get seconds, then use the unixepoch modifier to get date, and use strftime to output only the year and month:
SELECT strftime('%Y-%m', DateMillis / 1000, 'unixepoch'),
COUNT(*)
FROM MyTable
GROUP BY 1
If you want to store a date, use date type. Sqlite may not have it. But please, do not use it as string! I would suggest you to store integer to store miliseconds sice epoch. Use bindLong() and such. Unfortunately, you have to make some computations yourself in code. Just compute first and last milisecond of each day. Then you would be able to use WHERE timestamp BETWEEN first_day_milisecond AND last_day_milisecond, using even indexes.
You can select min and max of timestamp to try only days between them.
If you need to do this frequently or over a lot of data, I suggest to store date in multiple columns as integers for year, month, day. Depends on what you have to do with time, miliseconds since midnight. Or more columns of hour, minute, second and miliseconds.
I think it is much easier to format string date from bunch of numbers than parsing those numbers from a string. Definitely easier to compare them inside database.
I want to make a query to get records between specified hours. For example, i want to get all records between 00:00 and 01:00 for all days. So, the date does not matter but hours. How to do that?
I have done this, but it only return for certain dates.
Select name from my_table where date_column> beginning and date_column< end
Here beginning and end are in millisecond. Also my date_column is stored in millisecond format.
Use strftime():
Select name
from my_table
where strftime('%H', date_column) = '00';
This just checks the hour. You could use '%H:%M:%S' if you wanted more granularity.
EDIT:
You do not have a date time value. You have something else. It looks like a Unix epoch time measured in milliseconds rather than seconds. If so, the following should work:
Select name, datetime(date_column/1000, 'unixepoch')
from my_table
where strftime('%H', datetime(date_column/1000, 'unixepoch')) = '19';
However, none of the times are at hour 3. You may need to convert using your localtime.
I have been stuck with this problem for a while (Android SQLITE). I have 2 columns - Date and Amount. Date is stored in YYYYMMDD format.
DATE AMOUNT
20120521-------50
20120506-------40
20120311-------30
20120202-------20
20120125-------10
What I need is a SQL query (Android SQLITE), which will output two columns - Month and cumulative total till that month..If a month does not have any transaction, it still should evaluate the cummulative total.
So the output I need here (notice there are no transactions for April)
Month Cumulative-Total
MAY-------150
APR-------60
MAR-------60
FEB-------30
JAN-------10
It should work:
SELECT strftime('%m', date), SUM(Amount)
FROM myTable
GROUP BY strftime('%m', date)
Sorry i forgot this part of your question "..If a month does not have any transaction, it still should evaluate the cummulative total."
Solution: The simple solution is to have a DUMMY entry in the table for all months.
Difficult since the easy way to do this is to write a stored procedure to do it but which isnt supported in sqlite. However take a look at this - maybe this way might be useful
Android - easy/efficient way to maintain a "cumulative sum" for a SQLite column
Also you can try doing the cumulative addition on the android end
you can not just comulate like this. You can do this 2 ways:
Group by month and then sum it up on the Android end and add the Months that missing.
Try make that with a store procedure. (this I am not entierly sure possable on sql lite for your case.) Read this
So I would go with the first option.
In my Android App I need to keep track of the longest streak, and current streak, of consecutive dates that are saved in a database table. I don't even know where to start to get this to work. The best I can come up with is to query every row in the table and iterate through all of them programmatically to find where there's a gap. Not very efficient. Anyone have any better ideas?
Here is an SQL only solution that I thought was really cool. Assuming the dates in your table are unique (not that it would be too hard to just group on them) you can use the method adapted from here http://www.sqlteam.com/article/detecting-runs-or-streaks-in-your-data. I ran through the example and there are some syntax errors, so hopefully I didn't repeat them in my answer below. I probably used some reserved keywords, so you may need to adapt that.
First create a table of Dates that is significantly large to cover your needs. I'm not sure what the best method for SQLite is, but in SQL Server you can insert integers into a Datetime field and it will do an implicit conversion of integers to dates. There are many methods to insert integers into tables...
Anyway, once the Dates table is created, do a left join from your Dates table to your Streak table using your min and max dates from your streak table as your range limiter. You will then have the following code.
Let’s call it SQL 0
SELECT Dates.Date,
CASE
WHEN StreakTable.DATE IS NULL THEN 0
ELSE 1
END AS Result
FROM Dates
LEFT JOIN StreakTable
ON Dates.DATE = StreakTable.DATE
WHERE Dates.DATE BETWEEN (SELECT MIN(DATE) AS MinDate
FROM StreakTable) AND (SELECT MAX(DATE) AS MaxDate
FROM StreakTable)
Let’s call the following SQL 1
SELECT Date,
Result,
(SELECT COUNT(*)
FROM (SQL 0) S
WHERE S.Result <> SV.Result
AND S.GameDate <= SV.GameDate) AS RunGroup
FROM (SQL 0) SV
Let’s call the following SQL 2
SELECT Result,
MIN(Date) AS StartDate,
MAX(Date) AS EndDate,
COUNT(*) AS Days
FROM (SQL 1) A
GROUP BY Result,
RunGroup
ORDER BY MIN(Date)
At this point you can do some pretty cool stuff like answer:
What was the longest streak?
SELECT TOP 1 *
FROM (SQL 2) A
WHERE Result = 1
ORDER BY Games DESC
What is the current streak as of the most recent date?
SELECT *
FROM (SQL2) A
WHERE EndDate = (SELECT Max(Date)
FROM Streak)
How many streaks of 3 or more did we have?
SELECT Result,
COUNT(*) as NumberOfStreaks
FROM (SQL 2) A
GROUP BY Result
WHERE Days >= 3
Basically you have a month and days in a month
so you just compare the days count to the needed number.
If there's a gap you can easily find it out by substracting the count from days in a month. E.g. you have count(days_visited) where month=1
and it returns you 20 days but January has 31 so there's a gap in 11 days and here're the date functions of sqlite
http://www.sqlite.org/lang_datefunc.html
You can use following functions
like SELECT date('now','start of year','+9 months','weekday 2');
EDIT
sorry everyone solution is ugly. it is I know.
create table visits(day_visited timestamp,visited int);
You create a record everyday in this table indicating
whether a user was online or offline with
'now',1 or 0 (online/offline). Then you run through there records.
Your records for month will be an int array with 1s and 0s.
called vistedrecordsformonth
pseudo code:
int online=0;
int offline=0;
for(int i=0;i<vistedrecordsformonth.size();i++){
boolean flag=false;
if(vistedrecordsformonth[i]==1){ //visited
if(!flag&&i!=0) //check for flag and not 0 index to insert a record
{
streaksMap.put(online,offline); //or insert a record into another streakmap or table
online=0;
offline=0;
}
flag=true;
online++;
}
else{
flag=false;
offline++;
}
} //end of for
The map or table will contain a pair of online=offline days for a month.
with usual order by you can see what was the biggest streak in online or offline days.
It is ugly I know I'm sure there should be something more elegant but as
quick and dirty it should work.
hope it helps abit.
I have a sqlite database. I have three columns:_id, date, value.
I now want to extract a count of the _id:s depending on the day in the date, and calculate an average of the int value. This is for an Android app.
So I want to "select the day in date and for each day ( for sixty days), count how many _id:s there are for this day. Finally calculate the average of value.
I guess it is something like :
"SELECT DATE('now' 'days[i]') as date, COUNT(_id) as count, AVG(value) as vl FROM v_efforts WHERE DATE(v_efforts.date) = DATE('now' 'days[i]')";
But I can't get the 'days[i]' to work. I don't know how i can get this value to increase to sixty, and then how I can store the count and vl for each of these sixty days.
THanks a lot!
You'll want to use a GROUP BY expression to aggregate the entries by date. It's not quite clear whether you're looking for the last 60 days of entries in the database, or the entries from the last 60 real days (which would only be the same if you can assume that there are entries every day).
For the former (last 60 days which had database entries), you can use a LIMIT clause:
SELECT date,COUNT(_id),AVG(value) FROM v_efforts GROUP BY date ORDER BY date DESC LIMIT 60;
For the latter (last 60 real days), you can use WHERE:
SELECT date,COUNT(_id),AVG(value) FROM v_efforts WHERE date>DATE('now','-60 days') GROUP BY date ORDER BY date DESC;
The docs for Version 3 are pretty decent:
http://www.sqlite.org/lang_datefunc.html
I would look at the block that deals with the built in date time functions. Since SQLite doesn't support an actual date datetype:
Compute the current date:
SELECT date('now');
Compute the last day of the current month:
SELECT date('now','start of month','+1
month','-1 day');
Compute the date and time given a unix timestamp 1092941466.
SELECT datetime(1092941466,
'unixepoch');
Compute the date and time given a unix timestamp 1092941466, and compensate for your local timezone.
SELECT datetime(1092941466,
'unixepoch', 'localtime');
Compute the current unix timestamp.
SELECT strftime('%s','now');
Compute the number of days since the signing of the US Declaration of Independence.
SELECT julianday('now') -
julianday('1776-07-04');
Compute the number of seconds since a particular moment in 2004:
SELECT strftime('%s','now') -
strftime('%s','2004-01-01 02:34:56');
Compute the date of the first Tuesday in October for the current year.
SELECT date('now','start of year','+9
months','weekday 2');
Compute the time since the unix epoch in seconds (like strftime('%s','now') except includes fractional part):
SELECT (julianday('now') -
2440587.5)*86400.0;