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
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
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.
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.
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.