Assume I have the following SQLite table "foobar":
id | start | duration
---+------------+---------
1 | 2016-05-12 | 2
2 | 2016-01-01 | 5
My goal is to get the sum of the start-date and the duration (durations are in years).
So my desired result is the following:
id | end
---+-----------
1 | 2018-05-12
2 | 2021-01-01
Is this possible with a single query?
I know it is possible to add static values as follows
SELECT date(start, "+2 years") FROM foobar;
but I could not find a way to replace the static 2 with the dynamic value of duration.
SELECT date(start, "+" || duration || " years")
FROM foobar;
SQLFiddle demo
Related
I need to count the number of unique values and to group them by day.
For example, I have :
user id | Date
1 | 01.-11-2018
1 | 01-11-2018
2 | 02-11-2018
3 | 03-11-2018
1 | 03-11-2018
In result i need
01-11-2018 | 1
02-11-2018 | 1
03-11-2018 | 2
I need do it in Klipfolio
You can use the GROUPBY() function with the aggregation in the method parameter set to Count Distinct. For example, if your dates are in column A of a spreadsheet and your values are in column B, your formula would look like this:
GROUPBY(#A:A,#B:B,Count Distinct)
I have a dataset like shown below (except the Ser_NO, this is the field i want to create).
+--------+------------+--------+
| CaseID | Order_Date | Ser_No |
+--------+------------+--------+
| 44 | 22-01-2018 | 1 |
+--------+------------+--------+
| 44 | 24-02-2018 | 3 |
+--------+------------+--------+
| 44 | 12-02-2018 | 2 |
+--------+------------+--------+
| 100 | 24-01-2018 | 1 |
+--------+------------+--------+
| 100 | 26-01-2018 | 2 |
+--------+------------+--------+
| 100 | 27-01-2018 | 3 |
+--------+------------+--------+
How can i achieve a serial number for each CaseId based on my dates. So the first date in a specific CaseID gets number 1, the second date in this CaseID gets number 2 and so on.
I'm working with T-SQL btw,
I've tried a few things:
CASE
WHEN COUNT(CaseID) > 1
THEN ORDER BY (Order_Date)
AND Ser_no +1
END
Thanks in advance.
First of all, although I don't understand what you did, it gives you what you wanted. The serial number is assigned by date order. The problem I can see is that the result shows you the rows in the wrong order (1, 3, 2 instead of 1, 2, 3).
To sort that order you can try this:
SELECT *, ROW_NUMBER() OVER (PARTITION BY caseid ORDER BY caseid, order_date) AS ser_no
FROM [Table]
Thanks for your reply,
Sorry for the misunderstanding, because the ser_no is not yet in my table. That is the field a want to calculate.
I finished it myself this morning, but it looks almost the same like your measure:
RANK() OVER(PARTITION BY CaseID ORDER BY CaseID, Order_Date ASC
I have the following table:
date | id
-----------|------
unixtime_1 | 2
unixtime_1 | 7
unixtime_1 | 9
unixtime_1 | 24
unixtime_1 | 29
unixtime_1 | 21
unixtime_2 | 8
So far I get the results from such a table doing so:
SELECT date, id FROM table ORDER BY date DESC, id ASC
and I get
unixtime_1 | 2
unixtime_1 | 7
unixtime_1 | 9
unixtime_1 | 21
unixtime_1 | 24
unixtime_1 | 29
unixtime_2 | 8
I was wondering whether I could LIMIT the result so that in the range id=1-10 id=11-20 and id=21-30 I could get in the result only the record with the higher id.
So:
unixtime_1 | 9
unixtime_1 | 29
Since for id range=11-20 there isn't any record, it should be skip the range.
The range now are 1-10, 11-20, 21-30 but are custom ranges set by me according to the user request so I should be able to change them.
Is that possible via query?
Thank you
Your latest requirement should be possible to achieve merely by grouping by the date and (id - 1) / <some_number>, where in your example <some_number> would be 10.
SELECT t1.*
FROM yourTable t1
INNER JOIN
(
SELECT date, (id - 1) / 10 AS id_grp, MAX(id) AS max_id
FROM yourTable
GROUP BY date, (id - 1) / 10
) t2
ON t1.date = t2.date AND t1.id = t2.max_id
ORDER BY
t1.date, t1.id;
You may choose any range you want 1 - num by simply replacing 10 in my query with the end of the range.
If i did understand correctly and if your range is id=1-3
you could simply do:
SELECT id, date FROM table WHERE id>=1 AND id<=3 ORDER by id DESC, date DESC limit 1;
this will give you only 1 record with the highest id in the range id=1-3.
you can store it and perform another query for another range and combine them later
Try this:
SELECT date, MAX(ID) FROM table GROUP BY date
I have a project that calculates work hour from the attendance logs that I import from attendance machine. I use SQLite database and VB .NET.
First I'll show the table that I use:
CREATE TABLE [CheckLogs] (
[IDCheckLog] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
[IDEmployee] TEXT NOT NULL,
[Dates] TEXT NOT NULL,
[In] TEXT,
[Out] TEXT,
[OverTime] NUMERIC DEFAULT 0);
CREATE TABLE integers (i INTEGER NOT NULL PRIMARY KEY);
INSERT INTO integers (i) VALUES
(0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
Table CheckLogs is the data that I import from the attendance machine. The OverTime column is calculated in my program. Table integer is used to create the date list, I got it from here.
I want to generate a view that shows employee attendance between 2 dates and display the CheckLogs data if the employee is present and null if absent. Because in the table CheckLogs, when the employee is absent then there is no data from that day from this employee.
This is the view that I desired (this is report for employee 10001 between 2014-10-01 and 2014-10-05):
Dates | IDEmployee | In | Out
---------------------------------------
2014-10-01 | 10001 | 07:00 | 16:00
2014-10-02 | 10001 | 07:01 | 15:58
2014-10-03 | 10001 | null | null
2014-10-04 | 10001 | 07:08 | 15:48
2014-10-05 | 10001 | null | null
And this is the query that I have now:
SELECT X.[Dates], C.[IDEmployee], C.[In], C.[Out]
FROM
(select date('2014-10-01', '+' || (H.i*100 + T.i*10 + U.i) || ' day') as Dates
from integers as H
cross
join integers as T
cross
join integers as U
where date('2005-01-25', '+' || (H.i*100 + T.i*10 + U.i) || ' day') <= '2014-10-05') AS X
, CheckLogs AS C USING (Dates)
WHERE C.[IDEmployee]='10001'
From this query I have this result:
Dates | IDEmployee | In | Out
---------------------------------------
2014-10-01 | 10001 | 07:00 | 16:00
2014-10-02 | 10001 | 07:01 | 15:58
2014-10-04 | 10001 | 07:08 | 15:48
To get NULL values for rows without a match, you need an outer join.
And you have to take care not to filter out those rows with a WHERE clause that would not match NULL values; to get dates that do not match a condition, you have to put that condition into the join's ON clause:
SELECT ...
FROM ( ... ) AS X
LEFT JOIN CheckLogs AS C ON C.Dates = X.Dates AND
C.IDEmployee = '10001'
I need to pull a row in a select statement from a SQL database if a certain value in a table is changed.
For example, I have a column called price in a Price table. If the user changes the value for price (through an asp.net app), I want to select that entire row. This is going to be done in a workflow and an email is sent to the user that the row that was changed AFTER it was changed.
Does this make sense? Can someone point me in the right direction of a procedure or function to use? Thanks.
You could use an SQL trigger to accomplish this.
There is a tutorial (using Price as you described) that shows how to accomplish this here: http://benreichelt.net/blog/2005/12/13/making-a-trigger-fire-on-column-change/
well, in order to update a row, you'll have to update that row "WHERE uniqueID = [someid]". Can't you simply run a select immediately after that? (SELECT * FROM [table] WHERE uniquueID = [someid])
Without knowing what your data looks like (or what database this is, it's a little difficult) but assuming you have a history table with a date and an ID that stays the same like this...
+----+-------+------------+
| ID | PRICE | CHNG_DATE |
+----+-------+------------+
| 1 | 2.5 | 2001-01-01 |
| 1 | 42 | 2001-01-01 |
| 2 | 4 | 2001-01-01 |
| 2 | 4 | 2001-01-01 |
| 3 | 4 | 2001-01-01 |
| 3 | 3 | 2001-01-01 |
| 3 | 2 | 2001-01-01 |
+----+-------+------------+
and your database supports With and Row_number You could write the following
WITH data
AS (SELECT id,
price,
chng_date,
Row_number()
OVER (
partition BY id
ORDER BY chng_date) rn
FROM price)
SELECT data.id,
data.price new,
data_prv.price old,
data.chng_date
FROM data
INNER JOIN data data_prv
ON data.id = data_prv.id
AND data.rn = data_prv.rn + 1
WHERE data.price <> data_prv.price
That would produce this
+----+-----+-----+------------+
| ID | NEW | OLD | CHNG_DATE |
+----+-----+-----+------------+
| 1 | 42 | 2.5 | 2001-01-01 |
| 3 | 3 | 4 | 2001-01-01 |
| 3 | 2 | 3 | 2001-01-01 |
+----+-----+-----+------------+
Demo
If your Database supports LAG() its even eaiser
WITH data
AS (SELECT id,
price new,
chng_date,
Lag(price)
OVER (
partition BY id
ORDER BY chng_date) old
FROM price)
SELECT id,
new,
old,
chng_date
FROM data
WHERE new <> old
Demo