SQLite UPDATE Statement - sqlite

SQLite UPDATE Statement
I have two tables:
Table1
ID Num
1
2
3
4
5
Table2
ID
1
1
2
2
2
3
3
4
4
4
5
I need to UPDATE the Num field in Table1 with occurences of the ID field in Table2 i.e. based on previous:
Table1
ID Num
1 2
2 3
3 2
4 3
5 1
If i run this SQLite statement:
SELECT COUNT(t2.ID) FROM Table1 t1,Table2 t2 WHERE t1.ID=t2.ID GROUP BY t2.ID;
i have the correct table but when i try to UPDATE with that statement:
UPDATE Table1
SET Num=(SELECT COUNT(t2.ID) FROM Table1 t1,Table2 t2 WHERE t1.ID=t2.ID GROUP BY t2.ID);
i have nonsense output.Any ideas?

You must use a correlated subquery to correlate the value returned by the subquery with the current row in the outer query.
This means that you must not use Table1 again in the subquery, but instead refer to the outer table (with the actual name; the UPDATEd table does not support an alias):
UPDATE Table1
SET Num = (SELECT COUNT(t2.ID)
FROM Table2 t2
WHERE Table1.ID=t2.ID
GROUP BY t2.ID);

Related

how do i update mulitple rows with dynamic data?

I am using SQLite to update mulipte rows, but it does not work.
item table to keep the item data
item_ID Qty
- -
1 10
2 10
3 10
user_basket table to keep users' basket data
user_ID item_ID Bask_Qty
- - -
1 1 5
1 2 1
2 1 1
I used command like:
UPDATE item
SET Qty =
(SELECT Qty-Bask_Qty FROM user_basket
INNER JOIN item ON item.item_ID = user_basket.item_ID)
WHERE item_ID IN (SELECT item_ID FROM user_basket WHERE user_ID = 1);
After the command, I should expect item table be like that:
item_ID Qty
- -
1 5
2 9
3 10
but instead, I got:
item_ID Qty
- -
1 5
2 5
3 10
apparently, it used the same value to update all the rows.
Use a correlated subquery:
UPDATE item AS i
SET Qty = i.Qty - COALESCE(
(SELECT SUM(b.Bask_Qty) FROM user_basket b WHERE b.user_ID = 1 AND b.item_ID = i.item_ID),
0
)
See the demo.
Or, with a WHERE clause to avoid unnecessary updates:
UPDATE item AS i
SET Qty = i.Qty - (SELECT SUM(b.Bask_Qty) FROM user_basket b WHERE b.user_ID = 1 AND b.item_ID = i.item_ID)
WHERE EXISTS (SELECT 1 FROM user_basket b WHERE b.user_ID = 1 AND b.item_ID = i.item_ID)
See the demo.
If your version of SQLite is 3.33.0+ you can use UPDATE...FROM syntax:
UPDATE item AS i
SET Qty = i.Qty - b.Bask_Qty
FROM (SELECT item_ID, SUM(Bask_Qty) Bask_Qty FROM user_basket WHERE user_id = 1 GROUP BY item_ID) AS b
WHERE b.item_id = i.item_id
In all of the above queries I used SUM(Bask_Qty) to return the quantity of each item from the table user_basket, just in case there are more than 1 rows for each item.
If you are sure that there may be only 1 row for each item then replace it with just Bask_Qty.

Updating a column based on conditions

I have a table like:
ID ID2 Name
1 1
2 1
3 2
4 2
5 2
6 3
7 3
8 3
I want to Update the Name column with Values like Name1, name 2 and so on.
This will be based on condition if there are two similar values in ID2 column, for example, the first two rows, then the Name column to be updated with values Name1 and Name2 respectively.Next rows would be Name1, Name2, Name3 respectively and so on. Can someone help me with the logic for this?
ROW_NUMBER with a partition on the ID2 column, ordered by the ID column, should generate the sequences you want. Try this update query:
UPDATE yourTable t1
SET Name = (SELECT 'Name' || t.rn FROM
(
SELECT t2.ID, t2.ID2,
ROW_NUMBER() OVER (PARTITION BY t2.ID2 ORDER BY t2.ID) rn
FROM yourTable t2
WHERE t1.ID = t2.ID AND t1.ID2 = t2.ID2
) t)

find values which are the same as value above in sqlite

I am trying to find values which are the same as at least two values above it. Please take a look.
id number
1 2
2 6
3 7
4 7
5 7
6 1
7 2
8 4
9 7
So in this case select would return:
ID NUMBER
3 7
4 7
5 7
You can look up values in othe rows with a correlated subquery:
SELECT *
FROM MyTable
WHERE number = (SELECT number
FROM MyTable AS T2
WHERE T2.id = MyTable.id - 1)
AND number = (SELECT number
FROM MyTable AS T2
WHERE T2.id = MyTable.id - 2);

proc sql count by two groups or variables

I have some data that looks like this:
ID flag
A 1
A 1
A 2
B 1
B 2
B 3
How do I use proc sql to count the Id by flag so that the outcome looks like this?:
ID flag count
A 1 2
A 2 1
B 1 1
B 2 1
B 3 1
The query I used does not seem to be correct since it returns the distinct types of flag, not how many of each type of flag there are.
proc sql;
select Id, flag, count(flag) as count from table
group by Id;
You need to include flag in your grouping.
proc sql;
select Id, flag, count(1) as count from table
group by Id, flag;
quit;

pl/sql Compare with previous row

The goal is to combine Time_a within 10 min interval that has same ID.
And group the ID.
ID Time_a -> ID
------------ ----------
1 12:10:00 1
1 12:15:00 2
1 12:20:00 2
2 12:25:00
2 12:35:00
2 02:00:00
It became two '2' because time interval between row5 and row6 is more than 10 min.
I was able to combine within 10-min difference, but it doesn't distinguish ID.
select ID
from(
select id, Time_a, min(time) OVER (order by id, time rows between 1 preceding and 1 preceding) prev_t_stamp
from dual
)
where abs(Time_a-prev_t_stamp)>10/1440
If time_a is date then it works as follow. If it is a timestamp you need to cast it to a date otherwise it will not quite work. Here is my test script
drop table test;
create table test (id number, time_a date);
insert into test values (1, to_date('12:10','HH24:MI'));
insert into test values (1, to_date('12:15','HH24:MI'));
insert into test values (1, to_date('12:20','HH24:MI'));
insert into test values (2, to_date('12:25','HH24:MI'));
insert into test values (2, to_date('12:35','HH24:MI'));
insert into test values (2, to_date('14:00','HH24:MI'));
select id from (
select distinct id, case from (
select ID,case when abs(Time_a-prev_t_stamp)>10/1440 then '>' end case
from(
select id, Time_a, min(time_a) OVER (order by id, time_a rows between 1 preceding and 1 preceding) prev_t_stamp
from test
)
)
) order by 1
This results into:
table TEST dropped.
table TEST created.
1 rows inserted.
1 rows inserted.
1 rows inserted.
1 rows inserted.
1 rows inserted.
1 rows inserted.
ID
--
1
2
2

Resources