How to get self-differences in sqlite table - sqlite

does anyone know if there is a way to get this result in SQLite.
Given table with single column x like this:
x |
--
1
4
5
2
I need to add column dx, which is simply a difference x_i - x_{i-1} (except for the first one) like this:
x | dx |
-- --
1 | 0
4 | 3
5 | 1
2 | -3
Thanks a lot!
Update: given there is id column:
id | x |
-- --
1 | 1
2 | 4
3 | 5
4 | 2
Is it possible to obtain:
id | x | dx |
-- -- --
1 | 1 | 0
2 | 4 | 3
3 | 5 | 1
4 | 2 | -3

SQL tables have no implicit order associated with them. You must supply an ORDER BY clause to impose an order on the results.
What column would you order by to define the predecessor row for the subtraction? (Hint: there is none.)
With the addition of an id column per the revised question
sqlite> select id, x, (select t1.x - t2.x from t as t2 where id = t1.id - 1) from t as t1;
1|1|
2|4|3
3|5|1
4|2|-3
Or
sqlite> select id, x, coalesce((select t1.x - t2.x from t as t2 where id = t1.id - 1),0) from t as t1;
1|1|0
2|4|3
3|5|1
4|2|-3

Related

BigQuery - Duplicate rows x time using recursive method

I tried duplicating all rows in a table using the recursive method.
I have this base table
base
+------+
| rn |
+------+
| 1 |
| 2 |
| 3 |
+------+
Then, I want to replicate each of rows 3 times so the expected output would be like (9 rows)
+------+-------------+
| rn | iteration |
+------+-------------+
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 1 | 2 |
| 2 | 2 |
| 3 | 2 |
| 1 | 3 |
| 2 | 3 |
| 3 | 3 |
+------+-------------+
I want to use recursive method
WITH recursive test AS (
SELECT
*,
1 AS iteration
FROM `base`
UNION ALL
SELECT
a.*,
b.iteration + 1 AS iteration
FROM `base` a
JOIN test b ON b.iteration < 3
)
SELECT *
FROM test
ORDER BY 2,1
But the result is not what I expected, it would produce 39 rows instead of 9 rows, it seems it's because of the JOIN that using cross join. Is there any way to fix the query to produce the expected value?
Thanks in advance!
Instead of RECURSIVE CTE, you can consider below
WITH base AS (
SELECT * FROM UNNEST([1, 2, 3]) rn
)
SELECT *
FROM base, UNNEST(GENERATE_ARRAY(1, 3)) iteration;
Query results
And for recursive approach, you need to add another join condition a.rn = b.rn.
WITH RECURSIVE base AS (
SELECT * FROM UNNEST([1, 2, 3]) rn
),
test AS (
SELECT *, 1 AS iteration FROM base
UNION ALL
SELECT b.*, a.iteration + 1
FROM test a
JOIN `base` b ON a.rn = b.rn AND a.iteration < 3
)
SELECT * FROM test ORDER BY 2,1;

PL/SQL: Creating a grid (like an excel table) with the intersection of 2 selects, one for rows and the other for columns

I have 3 sets of values i wish to display
Class
Duration
Students
The columns of the tables are as follows:
table 1: class - duration
table 2: class - student
The data would look like this:
table 1:
class - duration
1 - 6
2 - 12
3 - 18
4 - 24
Table 2:
class - student
1 - student 1
2 - student 2
2 - student 3
4 - student 3
the return from the select would look like this:
+-----------+---+----+----+----+
| | 6 | 12 | 18 | 24 |
+-----------+---+----+----+----+
| Student 1 | x | | | |
| Student 2 | | x | | |
| Student 3 | | x | | x |
+-----------+---+----+----+----+
thanks for the ideas!
With known durations, you can pivot data like this:
SELECT *
FROM ( SELECT student
, duration
FROM table1 t
JOIN table2 t2 ON t.class = t2.class )
PIVOT
(
count(duration)
FOR duration IN (6,12,18,24)
)
http://sqlfiddle.com/#!4/a8c7bb/57
Other propositions:
You can create dynamic query to fetch duration and create the list.
You can use PIVOT XML and then extractvalue into readable data
but you will need to know the number of returned columns

sqlite difference between rows

In SQLite I have a collection of records and I want to only show the records with specific differences.
The table has something like the following values:
file | idx | values
------|-------|----------------------
1 | 101 | 1,3,7,11,23,11
2 | 101 | 1,3,7,11,23,11
3 | 101 | 0,4,8,60,20,11
1 | 211 | 12,11,23
2 | 211 | 12,0,23
3 | 211 | 12,0,23
1 | 300 | 1
2 | 300 | 0
3 | 300 | 0
I want to be able to select two different fileIDs, and compare them.
I mean, I want to examine only records with (file = 1 AND file = 2)
What I cant to get back as a result is a collection of records that are not the same:
file | idx | values
------|-------|----------------------
1 | 211 | 12,11,23
2 | 211 | 12,0,23
1 | 300 | 1
2 | 300 | 0
So you do not want rows for which another row with the same idx and values values exists:
SELECT *
FROM MyTable
WHERE file IN (1, 2)
AND NOT EXISTS (SELECT *
FROM MyTable AS T2
WHERE file IN (1, 2)
AND file <> MyTable.file
AND idx = MyTable.idx
AND values = MyTable.values);
I just recieved an answer in another forum. This seems to work:
select * from thetable a, thetable b
where a.file <> b.file and a.idx = b.idx and a.values <> b.values and
a.file in (1, 2) and b.file in (1, 2);
Of course I change certain values as variables in a prepared statement. But it did the trick

distinct values as new columns & count

I'm trying to generate a summary from a table using SQLite as below.
I need to aggregate 1) number of times each model was driven, 2) total distance driven & 3) get distinct values for driver col & count the number of times each driver has driven the particular model - GROUP BY modelwith COUNT(model) & SUM(distance) will help with 1 & 2 - `I need help with the last part #3 , what is the right approach to find number of occurrences for each distinct values of a column and add them as new columns for each model ?
My table is:
id model datetime driver distance
---|-----|------------|--------|---------
1 | S | 04/03/2009 | john | 399
2 | X | 04/03/2009 | juliet | 244
3 | 3 | 04/03/2009 | borat | 555
4 | 3 | 03/03/2009 | john | 300
5 | X | 03/03/2009 | juliet | 200
6 | X | 03/03/2009 | borat | 500
7 | S | 24/12/2008 | borat | 600
8 | X | 01/01/2009 | borat | 700
Result would be
id model| drives distance john juliet borat
---|-----|--------|---------|------|------ |------
1 | S | 2 | 999 | 1 | 0 | 1
2 | X | 4 | 1644 | 0 | 2 | 2
3 | 3 | 2 | 855 | 1 | 0 | 1
OK... this time I got it!
select new_table.model, count (new_table.model) as drives, sum (new_table.distance) as distance,
sum(case when driver = 'john' then 1 else 0 end) as john,
sum(case when driver = 'juliet' then 1 else 0 end) as juliet,
sum(case when driver = 'borat' then 1 else 0 end) as borat
from new_table
group by model
It's not 100%, but this should get you most of the way there.
CREATE TABLE DBO.TEST_TABLE (ID INT,MODEL CHAR(1),DATETIME VARCHAR(255),DRIVER VARCHAR(255),DISTANCE INT)
INSERT INTO DBO.TEST_TABLE
VALUES
(1,'S','04/03/2009','JOHN',399)
,(2,'X','04/03/2009','JULIET',244)
,(3,'3','04/03/2009','BORAT',555)
,(4,'3','03/03/2009','JOHN',300)
,(5,'X','03/03/2009','JULIET',200)
,(6,'X','03/03/2009','BORAT',500)
,(7,'S','24/12/2008','BORAT',600)
,(8,'X','01/01/2009','BORAT',700)
Declare #Query_ nvarchar(MAX)
Declare #Cols_For_Pivot_ nvarchar(MAX)
SELECT #Cols_For_Pivot_= COALESCE(#Cols_For_Pivot_ + ',','') + QUOTENAME(DRIVER)
FROM (SELECT DISTINCT DRIVER FROM DBO.TEST_TABLE) AS PivotTable
IF OBJECT_ID('tempdb..#TEMP') IS NOT NULL DROP TABLE #TEMP
SET #Query_ =
N'SELECT DISTINCT
MODEL
,COUNT(DATETIME) OVER(PARTITION BY MODEL) AS DRIVES
,SUM(DISTANCE) OVER(PARTITION BY MODEL) AS DISTANCE
, ' + #Cols_For_Pivot_ + '
INTO #TEMP
FROM DBO.TEST_TABLE
PIVOT(COUNT(DRIVER)
FOR DRIVER IN (' + #Cols_For_Pivot_ + ')) AS P'
EXEC sp_executesql #Query_

update table in sorted order

I am maintaining table structure like below.
sortid | id | name
1 | 1 | aa
3 | 2 | cc
4 | 3 | cc
2 | 4 | bb
5 | 5 | dd
Where sortid is maintained according to ascending order of name.
Now I want to update name 'dd' to 'aa', such way that sort id is also updated to its correct value.
Update table set name="bb" where name like "dd";
After updating my table should become like below.
sortid | id | name
1 | 1 | aa
4 | 2 | cc
5 | 3 | cc
3 | 4 | bb
2 | 5 | aa
That sortid is the number of rows that would be sorted before this row.
So you can compute it by counting rows:
UPDATE MyTable
SET sortid = (SELECT COUNT(*)
FROM MyTable AS T2
WHERE T2.name < MyTable.name) +
(SELECT COUNT(*)
FROM MyTable AS T2
WHERE T2.name = MyTable.name
AND T2.id <= MyTable.id);
(The second subquery resolves duplicate sortid values that would result from duplicate names.)

Resources