sql - update statement from another table - sql

Can anyone help with the following select statement?
I have 2 tables and I need to update table#1 with data from table#2
The field to update is 'amount'
Table#1
date amount
1 2015-05-01 0
2 2015-05-02 0
3 2015-05-03 0
4 2015-05-04 0
5 2015-05-05 0
6 2015-05-06 0
7 2015-05-07 0
8 2015-05-08 0
table#2
date amount
1 2015-05-01 12
2 2015-05-04 23
3 2015-05-07 30
the update statement should take table#2 to update table#1 and this is how it should look like:
table#1
date amount
1 2015-05-01 12
2 2015-05-02 12
3 2015-05-03 12
4 2015-05-04 23
5 2015-05-05 23
6 2015-05-06 23
7 2015-05-07 30
8 2015-05-08 30

A standard way to do this is using a correlated subquery:
update t1
set amount = (select top 1 t2.amount
from t2
where t2.date <= t1.date
order by t2.date
);
The top might vary from database to database.

Related

Joining two tables where date in second table should be first date after date in first table i.e earliest date after date in first table

Problem statement description :-
I have two tables - table1 and table2 . table1 contains data of quantity buy of id=7 and table2 contain data of quantity sold of same id=7. Both table1 and table2 is sorted according to date i.e from oldest to latest date and every time only 1 quantity is buy or sold.
table1:
table1
date_buy
id
qty_buy
rolling_sum_qty_buy
30-07-2019
7
1
1
20-10-2019
7
1
2
17-01-2020
7
1
3
15-02-2020
7
1
4
15-02-2020
7
1
5
15-02-2020
7
1
6
14-07-2021
7
1
7
19-09-2021
7
1
8
25-12-2021
7
1
9
30-12-2021
7
1
10
10-02-2022
7
1
11
15-03-2022
7
1
12
15-03-2022
7
1
13
14-06-2022
7
1
14
table2:-
table2
date_sold
id
qty_sold
rolling_sum_qty_sold
01-08-2019
7
1
1
15-09-2019
7
1
2
27-12-2019
7
1
3
01-02-2020
7
1
4
12-02-2020
7
1
5
25-07-2021
7
1
6
25-07-2021
7
1
7
28-08-2021
7
1
8
10-09-2021
7
1
9
12-09-2021
7
1
10
25-04-2022
7
1
11
-- SQL scrtpt of table1:
CREATE TABLE IF NOT EXISTS table1 (
`date_buy` DATETIME,
`id` INT,
`qty_buy` INT,
`rolling_sum_qty_buy` INT
);
INSERT INTO table1 VALUES
('2019-07-30 00:00:00',7,1,1),
('2019-10-20 00:00:00',7,1,2),
('2020-01-17 00:00:00',7,1,3),
('2020-02-15 00:00:00',7,1,4),
('2020-02-15 00:00:00',7,1,5),
('2020-02-15 00:00:00',7,1,6),
('2021-07-14 00:00:00',7,1,7),
('2021-09-19 00:00:00',7,1,8),
('2021-12-25 00:00:00',7,1,9),
('2021-12-30 00:00:00',7,1,10),
('2022-02-10 00:00:00',7,1,11),
('2022-03-15 00:00:00',7,1,12),
('2022-03-15 00:00:00',7,1,13),
('2022-06-14 00:00:00',7,1,14);
-- sql script of table2:
CREATE TABLE IF NOT EXISTS table2 (
`date_sold` DATETIME,
`id` INT,
`qty_sold` INT,
`rolling_sum_qty_sold` INT
);
INSERT INTO table2 VALUES
('2019-08-01 00:00:00',7,1,1),
('2019-09-15 00:00:00',7,1,2),
('2019-12-27 00:00:00',7,1,3),
('2020-02-01 00:00:00',7,1,4),
('2020-02-12 00:00:00',7,1,5),
('2021-07-25 00:00:00',7,1,6),
('2021-07-25 00:00:00',7,1,7),
('2021-08-28 00:00:00',7,1,8),
('2021-09-10 00:00:00',7,1,9),
('2021-09-12 00:00:00',7,1,10),
('2022-04-25 00:00:00',7,1,11);
-- Now, i want to join this two table on two condition
for every date i.e date_buy column in table1 i should get output where date i.e date_sold is greater than date_buy and i want first date i.e. date_sold which is greater than that particular date i.e date_buy.
i also want those rows from table1 in my output which does not get joined with table2
so that i can easily find out the remaining quantity because in table1 i have quantity buy and after joining with table2 i will get quantity sold, so the cases where i get null values then in that case i can assume that that much quantity is remaining.
--My output:-
Earlier when there was no date issue then i was simply using left join to join table1 and table2 on rolling sum condition and where there was null cases i was taking sum of qty to get remaining qty but right now i have that condition too so i cant use rolling_sum_cond column directly in join condition.
-- query which i was using and output which i was getting earlier
select * from table1
left join table2
on table1.rolling_sum_qty_buy=table2.rolling_sum_qty_sold
date_buy
id
qty_buy
rolling_sum_qty_buy
date_sold
id-2
qty_sold
rolling_sum_qty_sold
30-07-2019
7
1
1
01-08-2019
7
1
1
20-10-2019
7
1
2
15-09-2019
7
1
2
17-01-2020
7
1
3
27-12-2019
7
1
3
15-02-2020
7
1
4
01-02-2020
7
1
4
15-02-2020
7
1
5
12-02-2020
7
1
5
15-02-2020
7
1
6
25-07-2021
7
1
6
14-07-2021
7
1
7
25-07-2021
7
1
7
19-09-2021
7
1
8
28-08-2021
7
1
8
25-12-2021
7
1
9
10-09-2021
7
1
9
30-12-2021
7
1
10
12-09-2021
7
1
10
10-02-2022
7
1
11
25-04-2022
7
1
11
15-03-2022
7
1
12
NULL
NULL
NULL
NULL
15-03-2022
7
1
13
NULL
NULL
NULL
NULL
14-06-2022
7
1
14
NULL
NULL
NULL
NULL
and to find out remaining quantity , i was using null condition
query:-
with cte as
(
select * from table1
left join table2
on table1.rolling_sum_qty_buy=table2.rolling_sum_qty_sold
)
select sum(qty_buy) as remaining_qty
from cte
where cte.date_sold is null
remaining_qty
3
-- my expectation
now i have to use date condition also to get the output
-- Expected Output
date_buy
id
qty_buy
rolling_sum_qty_buy
date_sold
id
qty_sold
rolling_sum_qty_sold
30-07-2019
7
1
1
01-08-2019
7
1
1
20-10-2019
7
1
2
27-12-2019
7
1
3
17-01-2020
7
1
3
01-02-2020
7
1
4
15-02-2020
7
1
4
25-07-2021
7
1
6
15-02-2020
7
1
5
25-07-2021
7
1
7
15-02-2020
7
1
6
28-08-2021
7
1
8
14-07-2021
7
1
7
10-09-2021
7
1
9
19-09-2021
7
1
8
25-04-2022
7
1
11
25-12-2021
7
1
9
NULL
NULL
NULL
NULL
30-12-2021
7
1
10
NULL
NULL
NULL
NULL
10-02-2022
7
1
11
NULL
NULL
NULL
NULL
15-03-2022
7
1
12
NULL
NULL
NULL
NULL
15-03-2022
7
1
13
NULL
NULL
NULL
NULL
14-06-2022
7
1
14
NULL
NULL
NULL
NULL
-- Please help me to get the following output. Any help would be appreciated.
I am using postgresql.
That was a challenging one.
with recursive cte as
(
select t2.date_sold
,t2.rolling_sum_qty_sold
,true as is_match
,1 as last_rolling_sum_qty_buy
from t2 join t on t2.rolling_sum_qty_sold = t.rolling_sum_qty_buy
where t2.rolling_sum_qty_sold = 1
union all
select t2.date_sold
,t2.rolling_sum_qty_sold
,t2.date_sold >= t.date_buy
,cte.last_rolling_sum_qty_buy + case when t2.date_sold >= t.date_buy then 1 else 0 end
from t2
join cte on cte.rolling_sum_qty_sold + 1 = t2.rolling_sum_qty_sold
join t on t.rolling_sum_qty_buy = cte.last_rolling_sum_qty_buy + 1
)
select t.date_buy
,t.id
,t.qty_buy
,t.rolling_sum_qty_buy
,cte.date_sold
,cte.rolling_sum_qty_sold
from t left join cte on cte.last_rolling_sum_qty_buy = t.rolling_sum_qty_buy and is_match
date_buy
id
qty_buy
rolling_sum_qty_buy
date_sold
rolling_sum_qty_sold
2019-07-30
7
1
1
2019-08-01
1
2019-10-20
7
1
2
2019-12-27
3
2020-01-17
7
1
3
2020-02-01
4
2020-02-15
7
1
4
2021-07-25
6
2020-02-15
7
1
5
2021-07-25
7
2020-02-15
7
1
6
2021-08-28
8
2021-07-14
7
1
7
2021-09-10
9
2021-09-19
7
1
8
2022-04-25
11
2021-12-25
7
1
9
null
null
2021-12-30
7
1
10
null
null
2022-02-10
7
1
11
null
null
2022-03-15
7
1
12
null
null
2022-03-15
7
1
13
null
null
2022-06-14
7
1
14
null
null
Fiddle

Writing SQL INSERT which retrieves its data from two separate related rows

I am writing a SQL script that is to insert a new record using data from two rows that are under the same AccountID.
My table looks like the following:
AccountID | ActivityId | DisplayDetails | TransactionDate | EnvironmentId
============================================================================
1 7 Display1 2015-02-02 00:00:00.000 1
1 8 DisplayThis1 2018-02-02 00:00:00.000 1
1 7 Display2 1999-02-02 00:00:00.000 2
1 8 DisplayThis2 2000-02-02 00:00:00.000 2
My fix is to find find each 7,8 combination and insert a new row with ActivityId 78 that gets the DisplayDetails from ActivityId 7 and TransactionDate from ActivityId 8.
My queries looks like the following:
SELECT *
INTO #ActivityEight
FROM Account A
WHERE A.ActivityId = 8
INSERT INTO #Account (AccountId, ActivityId, DisplayDetails, TransactionDate)
SELECT VL.AccountId, 78, S.DisplayDetails, VL.TransactionDate
FROM #temp2 VL WITH(NOLOCK)
JOIN #ActivityEight S
ON VL.AccountId = S.AccountId
WHERE VL.ActivityId = 7
However when I run SELECT * FROM Account I get a 78 row for each 7 and 8 row, when I should only get 1 78 row per 7 and 8 combination.
AccountID | ActivityId | DisplayDetails | TransactionDate | EnvironmentId
=============================================================================
1 7 Display1 2015-02-02 00:00:00.000 1
1 8 DisplayThis1 2018-02-02 00:00:00.000 1
1 7 Display2 1999-02-02 00:00:00.000 2
1 8 DisplayThis2 2000-02-02 00:00:00.000 2
1 78 DisplayThis1 2015-02-02 00:00:00.000 NULL
1 78 DisplayThis2 2015-02-02 00:00:00.000 NULL
1 78 DisplayThis1 1999-02-02 00:00:00.000 NULL
1 78 DisplayThis2 1999-02-02 00:00:00.000 NULL
I believe I can utilize the EnvironmentId to achieve the desired functionality, but I'm not sure how.
Any help would be appreciated.
Thanks!
I think this will help you
INSERT INTO #Account (AccountId, ActivityId, DisplayDetails, TransactionDate)
SELECT VL.AccountId, 78, S.DisplayDetails, VL.TransactionDate
FROM Account VL WITH(NOLOCK)
JOIN Account S ON VL.AccountId = S.AccountId and VL.EnvironmentId = S.EnvironmentId
WHERE VL.ActivityId = 7 and S.ActivityId = 8

Construct a grouping column in SQL Server 2012

I have created a table that looks something like this:
ID TSPPLY_DT NEXT_DT DAYS_BTWN TIME_TO_EVENT CENSORED ENDPOINT
-----------------------------------------------------------------------------
1 2014-01-01 2014-01-10 10 10 0 0
1 2014-01-10 2014-01-21 11 21 0 0
1 2014-01-21 NULL NULL 21 1 0
2 2015-04-01 2015-04-30 30 30 0 0
2 2015-04-30 2015-05-03 1 31 0 1
2 2015-05-03 2015-05-06 3 34(should be 3)0 0
2 2015-05-06 2015-05-16 10 44(shouldbe 13)1 0
The TIME_TO_EVENT column however is not adding up correctly with my code - The idea is to add up the days between until either ID changes, CENSORED = 1 or ENDPOINT = 1.
I think what I need is an addition column where I can sum based on an aggregate of ID and GROUPING... With an output as follows:
ID TSPPLY_DT NEXT_DT DAYS_BTWN TIME_TO_EVENT CENSORED ENDPOINT GROUPING
----------------------------------------------------------------------------------------
1 2014-01-01 2014-01-10 10 10 0 0 A
1 2014-01-10 2014-01-21 11 21 0 0 A
1 2014-01-21 NULL NULL 21 1 0 A
2 2015-04-01 2015-04-30 30 30 0 0 A
2 2015-04-30 2015-05-03 1 31 0 1 A
2 2015-05-03 2015-05-06 3 3 0 0 B
2 2015-05-06 2015-05-16 10 13 1 0 B
So any ideas on how to create the GROUPING column? It would be something like IF next rows ID is the same as current row, check CENSORED AND ENDPOINT. If either = 1, for the next row, change the grouping to a new value. Once a new ID is reached, reset the grouping to A (or whatever arbitrary value) and run the test again.
You need to use the DATEDIFF function, like this:
DATEDIFF(d, TSPPLY_DT, NEXT_DT) AS DAYS_BTWN
Now you don't need GROUP BY.

SQL - Include a not exists line in a aggregation

I have a order table and I'm aggregation this table by this query:
SELECT dtdate, idsku, sum(vlorder) as vlorder, sum(qtditem) as qtditem
FROM order
GROUP BY dtdate, idsku
And I'm getting this results:
dtdate idsku vlorder qtditem
01/01/2016 1 4 8
02/01/2016 1 5 10
03/01/2016 1 3 6
04/01/2016 1 2 4
05/01/2016 1 3 6
06/01/2016 1 1 2
But, I don't have results for 07/01/2016 and idsku = 1 because doesn't exists on the database (sounds dummy). And I have to include this "empty" line 07/01/2016 1 0 0, like this:
dtdate idsku vlorder qtditem
01/01/2016 1 4 8
02/01/2016 1 5 10
03/01/2016 1 3 6
04/01/2016 1 2 4
05/01/2016 1 3 6
06/01/2016 1 1 2
07/01/2016 1 0 0
Is this possible?
In Postgres, you can use generate_series():
select g.mon, o.idsku,
sum(o.vlorder) as vlorder, sum(o.qtditem) as qtditem
from generate_series('2016-01-01'::timestamp, '2016-07-01'::timestamp,
interval '1' month) g(mon) left join
orders o
on o.dtdate = g.mon
group by g.mon, idsku;
If your dates are not on the first of the month, then you can use date_trunc('day', o.dtdate) = g.mon.

return the count of row even if null sql server

I trying to do a sql query to get the count for shift for each user
I used this query :
SELECT
COUNT(s.id) AS count, s.user_id
FROM
sarcuser AS u
INNER JOIN
sarcshiftpointuser AS s ON s.user_id = u.id
INNER JOIN
sarcalllevel AS l ON l.id = u.levelid
INNER JOIN
sarcshiftpointtable AS t ON t.shift_id = s.shift_id AND s.table_id = t.table_id
WHERE
(s.shift_id + '' LIKE '2')
AND (CAST(s.xdate AS DATE) BETWEEN CAST(N'2014-01-01' AS DATE) AND CAST(N'2015-01-01' AS DATE))
AND (u.gender + '' LIKE N'%')
AND (u.levelid + '' LIKE N'%')
AND (s.point_id + '' LIKE '2')
GROUP BY
s.user_id
ORDER BY
count
It works very well ... but there is a logic problem :
when the user didn't appear in the shift didn't return the count and I need it to return 0
For example :
user1 user2
shift1 2 2
shift2 5 0
shift3 6 10
but actually the code returns :
user1 user2
shift1 2 2
shift2 5 10
shift3 6
and that's wrong ... how to return the count even if it zero with this condition and this inner join ?
Sample for data in table :
sarcuser :
id firstname lastname gender levelid
52 samy sammour male 1
62 ibrahim jackob male 1
71 rebeca janson female 3
sarcalllevel :
id name
1 field leader
2 leader
3 paramdic
sarcshiftpointtable :
id shift_id table_id name_of_shift point_id
1 1 1 shift1 2
2 2 1 shift2 2
3 3 1 shift3 2
4 1 2 shift1 7
5 2 2 shift2 7
6 3 2 shift3 7
sarcshiftpointuser :
id point_id shift_id table_id user_id xdate
1 2 1 1 62 2014-01-05
2 2 1 1 0 2014-01-05
3 2 1 1 71 2014-01-05
4 2 2 1 0 2014-01-05
5 2 2 1 0 2014-01-05
6 2 2 1 52 2014-01-05
7 2 3 1 52 2014-01-05
8 2 3 1 62 2014-01-05
9 2 3 1 71 2014-01-05
10 2 1 1 71 2014-01-06
11 2 1 1 52 2014-01-06
12 2 1 1 0 2014-01-06
13 2 2 1 62 2014-01-06
14 2 2 1 0 2014-01-06
15 2 2 1 52 2014-01-06
16 2 3 1 62 2014-01-06
17 2 3 1 52 2014-01-06
18 2 3 1 71 2014-01-06
if i apply this query 3 times by changing the shift should return :
52 62 71
shift1 1 2 2
shift2 2 1 0
shift3 2 2 2
in shift2 in sarcshiftpointuser the user 71 is not appear
so when I do the code it will return just to field not three ? the count 0 is not returned
52 62 71
shift2 2 1
to be more specific :
I need to export this table into excel so when the 0 is not return it give me a wrong order and wrong value (logically )
You will need to use a nested query using IFNULL
Take a look to this
http://www.w3schools.com/sql/sql_isnull.asp
Something like,
IFNULL(user,0)
I think you are referring a crosstab query. you can use PIVOT to return your result set. Please refer below link.
Sql Server 2008 Cross Tab Query.
If you give few sample data for sarcuser , sarcshiftpointuser, sarcalllevel & sarcshiftpointtable tables, then we can give you a better answer.