Update one table from another doing some math - sql

Postgres 9.6.6, latest Ubuntu LTS.
I have a big main table and a small one, who receiving data from external sensors. Each record of the small one have the record id of the big one.
Table_1 Table_2
id temp0 temp0temp1 temp1 Tab1_Id
1 3 0 35 2
2 5 0 15 3
3 8 0 75 1
4 9 0 45 4
5 3 0 .some
6 8 0
7 2 0
.tens of thousand...
I'am looking for an efficient solution to update each record of the big one, doing some math, ie:
Table 1 (after)
id temp0 temp0temp1
1 3 78
2 5 40
3 8 23
4 9 54
5 3 0
6 8 0
7 2 0
Something similar to:
UPDATE Table_1
SET temp0temp1 = Table_1.temp0 + (SELECT temp1
FROM Table_2
WHERE table_2.Tab1_Id = Table_1.Id)...
Thanks
Perez

You can use a update ... from
UPDATE Table_1 t1
SET temp0temp1 = t1.temp0 + t2.temp1
from Table_2 t2
WHERE t2.Tab1_Id = t1.Id

You can create a trigger. On each insert of table 1 run a procedure that will update table 2 with desired calculations.

update t1
set temp0temp1 = temp0 + temp1
from Table_1 t1 join
Table_2 t2 on t1.id = t2.Tab1_Id

Related

LEFT JOIN with tables having boolean data producing unexpected result set

A Table_1 with only column BOOLVALUE(int) having records as
1
1
0
0
0
and another Table_2 with only column BOOLVALUE(int) having records as
1
1
1
0
0
.. I am trying to run a query
select t1.BOOLVALUE from Table_1 t1
left join Table_2 t2 on t1.BOOLVALUE=t2.BOOLVALUE
and to my surprise output is not what I expected.There are 12 rows with 6 1's and 6 0's. But doesn't this invalidates how joins work ?
12 rows is completely expected as you have 2 rows related to 3 rows, resulting in 6 rows, and 3 rows related to 2 rows resulting in 6 rows; add these together and you get 12.
When you JOIN all related rows are JOINed based on the ON clause. Your ON clause is t1.BOOLVALUE=t2.BOOLVALUE. This means all the 1s inTable_1 relate to all the 1s in Table_2; so that's 2 rows related to 3 rows (2 * 3). Then all the 0s inTable_1 relate to all the 0s in Table_2; so that's 3 rows related to 2 rows (3 * 2). Hence (2 * 3) + (3 * 2) = 6 + 6 = 12.
If we add an ID column to the table, this might become a little clearer.
Let's say you have 2 tables like this:
ID1
I1
1
1
2
1
3
0
4
0
5
0
ID2
I2
1
1
2
1
3
1
4
0
5
0
Then lets say you have the following query:
SELECT T1.ID1,
T2.ID2,
T1.I1,
T2.I2
FROM dbo.Table1 T1
JOIN dbo.Table2 T2 ON T1.I1 = T2.I2
ORDER BY T1.ID1
T2.ID2;
This would result in the following data set:
ID1
ID2
I1
I2
1
1
1
1
1
2
1
1
1
3
1
1
2
1
1
1
2
2
1
1
2
3
1
1
3
4
0
0
3
5
0
0
4
4
0
0
4
5
0
0
5
4
0
0
5
5
0
0
Here you can see you have a many to many join, and where the "extra" rows are coming from.
If you LEFT JOINed on the ID and I columns, starting at Table1, you would get 5 rows, with 1 row having NULL values for ID2 and I2 (in this case because although the ID matched, I did not):
SELECT T1.ID1,
T2.ID2,
T1.I1,
T2.I2
FROM dbo.Table1 T1
LEFT JOIN dbo.Table2 T2 ON T1.ID1 = T2.ID1
AND T1.I1 = T2.I2
ORDER BY T1.ID1
T2.ID2;
ID1
ID2
I1
I2
1
1
1
1
2
2
1
1
3
NULL
0
NULL
4
4
0
0
5
5
0
0
When you join on a column of which has repeating values the number of rows returned is the product of the number of matching values in the 2 tables.
In this case there are 2 1's in table 1 and 3 in table 2 so SQL returns the 6 possible combinations (2 x 3). As there are 3 x 2 zero combinations you get 12 rows in total.
If you did a cross join you would get 25 rows back (5 x 5).

Remove Duplicate Nodes from SQL Server Hierarchy

Looking at the below data is there an easy way to find IDs that exist at a higher level under the same leaf and remove them.
E.g. ID 4,5 exists in rows 4,5 , 8,9 and 12,13.
i want to remove rows 4,5 as the same IDs exist further down the hierarchy (rows 8,9), but rows 12,13 stay as they are on a separate leaf.
Rows to be Removed
row ID Path
1 1 /1/
2 2 /1/2/
3 3 /1/2/3/
4 4 /1/2/3/4/
5 5 /1/2/3/5/
6 6 /1/2/3/6/
7 7 /1/2/3/6/7/
8 4 /1/2/3/6/4/
9 5 /1/2/3/6/5/
10 8 /1/2/8/
11 7 /1/2/8/7/
12 4 /1/2/8/4/
13 5 /1/2/8/5/
example for max ID len = 1
select *
--delete t1
from table as t1
where exists(
select *
from table as t2
where left(t2.path, len(t1.path - 2)) = left(t1.path, len(t1.path - 2))
and charindex(right(t1.path, 2), t2.path, len(t1.path)) > 0
)
This is my approach it should work for any length of ID:
with
conversed as (
select substring(reverse(path),CHARINDEX('/',reverse(path),2), len(path)-CHARINDEX('/',reverse(path),2)) inverse_path, id, t.row
from t)
select c.id, c.row keeper, c1.row deletethis
from conversed c join conversed c1
on c.id = c1.id
and c.row <> c1.row
and c.inverse_path like '%' +c1.inverse_path;
OUTPUT
id keeper deletethis
4 8 4
5 9 5

SQL Inner Join and Partitioning To obtain RowNumbers when matching

I have 2 tables. The first table 'a' the second 'b'.
I am writing a query that grabs every row in table a (there is 33 rows defined) and inner joins table b where the EnclLocation or the BackPanLoc match the Workcell in table A.
I only want a row from table B where they match based off BackPan and EnclLocation but they are not the same records. table b has a few rows of data that is assigned to the same workcell as table a. I am just trying to retrieve those additional rows and partition it.
I attached table a and table b. I also attached the desired results for this query with respect to Workcell 10 only as an example... As you can see, table B has 4 records that has either the EnclLocation or the BackPanLoc = 10. But my results only show the same DelvNumber 4 times. any help is most appreicated.
Table a
Table b
Incorrect Results
Desired Results (showing only Workcell 10 as an example)
workcell DelvNumber RowNum
1 447910-02 1
2 445710-01 1
2 445710-01 2
3 444291-01 1
3 444291-01 2
4 447910-03 1
4 447910-03 2
5 648020-01 1
6 647800-02 1
7 646920-01 1
7 646920-01 2
8 644830-4-8 1
8 644830-4-8 2
9 443990-01 1
10 645960-01-03 1
10 445710-11 2
10 445710-02 3
10 445710-09 4
Code Used
WITH ss
AS (SELECT a.*,
Row_number()
OVER(
partition BY a.workcell
ORDER BY a.workcell) AS rownum
FROM nwcurrent a
INNER JOIN nwdeliverables b
ON b.encllocation = a.workcell
OR b.backpanloc = a.workcell
WHERE ( b.status < 9
AND ( b.encllocation <> 0
OR b.backpanloc <> 0 )
OR a.delvnumber = '123' ))
SELECT *
FROM ss
copy and paste format
1 447910-02 1
2 445710-01 1
2 445710-01 2
3 444291-01 1
3 444291-01 2
4 447910-03 1
4 447910-03 2
5 648020-01 1
6 647800-02 1
7 646920-01 1
7 646920-01 2
8 644830-4-8 1
8 644830-4-8 2
9 443990-01 1
10 645960-01-03 1
10 445710-11 2
10 445710-02 3
10 445710-09 4
SQLFiddle
http://sqlfiddle.com/#!3/a8682/4
A new try...
SELECT a.workcell
,a.DelvNumber AS A_DelvNumber
,b.DelvNumber AS B_DelvNumber
,CASE WHEN a.DelvNumber<>b.DelvNumber THEN b.DelvNumber ELSE a.DelvNumber END AS DelvNumber_Resolved
,Row_number() OVER(partition BY a.workcell ORDER BY a.workcell) AS rownum
FROM NWCurrent a
INNER JOIN NWDeliverables AS b ON b.EnclLocation=a.WorkCell OR b.BackPanLoc=a.WorkCell
WHERE (b.status <9 AND (b.EnclLocation<>0 OR b.BackPanLoc<>0)OR a.DelvNumber='123')

Fetch the latest records from many-to-many relationship table

I am using SQL Server 2008 R2.
I am having three tables in my database are having many-to-many relationship as below.
TblServiceLevel
Id ServiceLevel Code
1 C 1
2 R 1
3 V 1
4 R Test 4
5 C Test 4
6 S 2
7 K 3
TblUser
Id Name
1 A
2 B
3 C
4 D
5 E
6 F
TblUserServiceLevel
Id UserId ServiceLevelId Status
1 1 1 Active
2 1 1 Deactive
3 2 3 Active
4 3 4 Active
5 1 5 Active
6 5 1 Active
7 2 3 Deactive
8 3 4 Deactive
9 5 1 Deactive
10 2 3 Active
11 3 4 Active
12 4 1 Active
Now,
From this tables, I want distinct users that are exists in TblUserServiceLevel and
having latest service level ="Active" and ServiceLevel.Code <> 4.
Can anyone help me?
The result is 2 and 4 user id.
select t1.UserId
from TblUserServiceLevel t1
inner join (
select UserId, max (Id) as maxId
from TblUserServiceLevel
group by UserId
) t2 on t1.UserId = t2.UserId and t1.Id = t2.maxId
inner join TblServiceLevel sl on t1.ServiceLevelId = sl.Id and sl.Code <> 4
where t1.Status = 'Active'

MS-Access SQL loops

I would like to apply a for loop in this sql statement in ms-access something like:
for(i=0;i<8;i++)
{
UPDATE current_stock SET current_stock.quantity = DLookup("quantity","current_stock","stock_id=i")-DLookup("req_quantity","Bom_dell","lap_id=(SELECT lap_id FROM laptop_info WHERE model_name='Dell Inspiron')" And "stock_id=i")
WHERE stock_id=1;
}
Please advise if there is any method in MS-access to be able to do something similar to a for loop using sql queries.
Bom_dell
bom_id lap_id stock_id req_quantity
1 1 1 1
2 1 2 3
3 1 3 6
4 1 4 1
5 1 5 1
6 1 6 2
7 2 7 7
8 2 8 8
9 2 9 1
10 2 10 1
11 2 11 1
12 2 12 3
current_stock
ID lap_id stock_id quantity
1 1 1 11
2 1 2 11
3 1 3 11
lap_info
lap_id model_name model_num price
1 Dell Inspiron INS81 35000
2 Dell XLS XL91 24000
Sample query
UPDATE (SELECT laptop_info.model_name, current_stock.stock_id, Bom_dell.req_quantity, current_stock.quantity
FROM (current_stock INNER JOIN laptop_info ON current_stock.lap_id = laptop_info.lap_id) INNER JOIN Bom_dell ON current_stock.stock_id = Bom_dell.stock_id)
SET quantity=quantity-req_quantity
WHERE stock_id BETWEEN 1 AND 3
AND model_name='Dell Inspiron'
UPDATE (SELECT laptop_info.model_name, current_stock.stock_id, Bom_dell.req_quantity, current_stock.quantity
FROM (current_stock INNER JOIN laptop_info ON current_stock.lap_id = laptop_info.lap_id) INNER JOIN Bom_dell ON current_stock.stock_id = Bom_dell.stock_id) SET quantity = quantity-req_quantity
WHERE stock_id BETWEEN 1 AND 3
AND model_name IN ([Forms]![Invoice1]![laptop_id])
You seem to be looking for something on the lines of:
UPDATE (current_stock
INNER JOIN laptop_info ON laptop_info.stock_id=current_stock.stock_id)
INNER JOIN Bom_dell ON Bom_dell.lap_id = laptop_info.lap_id
SET current_stock.quantity = current_stock.quantity - Bom_dell.req_quantity
WHERE stock_id Between 1 And 8
AND model_name='Dell Inspiron'
Try this. I have used aliases - a is for the current_stock table and b is for the sub query. This assumes that you have one line per stock id in bom_dell.
UPDATE current_stock AS a
INNER JOIN (
SELECT bom_dell.stock_id, lap_info.model_name, bom_dell.req_quantity
FROM bom_dell
INNER JOIN lap_info ON bom_dell.lap_id = lap_info.lap_id
WHERE (((bom_dell.stock_id) Between 1 And 3)
AND ((lap_info.model_name)="Dell Inspiron"))) AS b
ON a.Stock_id = b.Stock_id SET a.quantity = [a].[quantity]+[b].[req_quantity];