SQL Gap Fill by ID - sql

I am attempting to gap fill in two scenarios. I can do it with one group but am uncertain with multiple
the data:
Order ID Amount
1 NULL NULL
2 A 500
3 NULL NULL
4 A 700
1 B 1000
2 NULL NULL
3 NULL NULL
4 B 1500
Target Result
Order ID Amount
1 A 500
2 A 500
3 A 700
4 A 700
1 B 1000
2 B 1500
3 B 1500
4 B 1500

Consider below approach
select * except(amount),
first_value(amount ignore nulls) over win as amount
from (select distinct `order` from your_table where not `order` is null),
(select distinct id from your_table where not id is null)
left join your_table using(`order`, id)
window win as (partition by id order by `order` rows between current row and unbounded following)
if applied to sample data in your question - output is

Related

Select quantity on a 1st table based on a total quantity the 2nd table

Table 1
ID
Grp
Qty
1
A
5
2
A
4
3
B
5
4
B
3
5
B
2
6
C
14
7
D
1
8
D
1
9
E
2
10
E
2
11
E
1
12
E
1
Table 2
ID
Grp
Qty
1
A
7
2
B
9
3
C
13
4
D
1
5
E
4
Select/Output
ID
Grp
Qty
1
A
0
2
A
2
3
B
0
4
B
0
5
B
1
6
C
1
7
D
0
8
D
1
9
E
0
10
E
0
11
E
1
12
E
1
I want to select a row on a 1st table with a specific quantity based on the total quantity of the 2nd table. The result is on the 3rd table. Please see sample tables above, I really appreciate a help, thank you so much and sorry it was my first time asking a question here.
I have tried this code on both 2 tables
WITH tbl AS(
SELECT ID,
Qty,
Grp,
ROW_NUMBER() OVER (PARTITION BY Grp)AS Rown,
SUM(Qty) OVER (PARTITION BY Grp)AS Total
FROM Table1
)
SELECT * FROM tbl WHERE Rown = 1
But I am not able to select the specific rows on Table 1 because it only select the 1st row and total the quantity. Every row on table 1 has its own quantity.
You could use a cumulative windowed aggregates and then a CASE expression to achieve this:
--Saple Data
WITH Table1 AS(
SELECT *
FROM (VALUES(1,'A',5),
(2,'A',4),
(3,'B',5),
(4,'B',3),
(5,'B',2),
(6,'C',14))V(ID,Grp,Qty)),
Table2 AS(
SELECT *
FROM (VALUES(1,'A',7),
(2,'B',9),
(3,'C',13))V(ID,Grp,Qty)),
--Solution
CTE AS(
SELECT T1.ID,
T1.Grp,
T1.Qty,
SUM(T1.Qty) OVER (PARTITION BY T1.Grp ORDER BY T1.Id
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS RunningQty,
T2.Qty AS T2Qty
FROM Table1 T1
JOIN Table2 T2 ON T1.Grp = T2.Grp)
SELECT C.ID,
C.Grp,
CASE WHEN C.RunningQty <= C.T2Qty THEN C.Qty
ELSE C.T2Qty - LAG(C.RunningQty,1,0) OVER (PARTITION BY C.Grp ORDER BY C.ID)
END AS Qty
FROM CTE C;

SQL: How do I display all records per unique id, but not the first record ever recorded in SQL

Example:
id Pricemoney time/date
1 100 01/20/2017
1 10 01/21/2017
1 1000 01/21/20147
2 10 01/23/2017
2 100 01/24/2017
3 1000 01/19/2017
3 100 01/22/2017
3 10 01/24/2017
I want to run a SQL query where I can display all the Id and it's pricemoney BUT NOT include the first record (based on time/date) per unique
Just to clarify what I do not want to be displayed
userid Pricemoney issuedate
1 100 01/20/2017 -- not included
1 10 01/21/2017
1 1000 01/21/20147
2 10 01/23/2017 --- not inlcuded
2 100 01/24/2017
3 1000 01/19/2017 -- not included
3 100 01/22/2017
3 10 01/24/2017
Expected result:
id Pricemoney time/date
1 10 01/21/2017
1 1000 01/21/20147
2 100 01/24/2017
3 100 01/22/2017
3 10 01/24/2017
You can use row_number():
select t.*
from (select t.*,
row_number() over (partition by id order by time_date asc) as seqnum
from <tablename> t
) t
where seqnum > 1;
If you want to keep single rows, you can do:
select t.*
from (select t.*,
row_number() over (partition by id order by time_date asc) as seqnum,
count(*) over (partition by id) as cnt
from <tablename> t
) t
where seqnum > 1 and cnt > 1;
You may use EXISTS
select t1.*
from data t1
where exists (
select 1
from data t2
where t1.id = t2.id and t2.time_date < t1.time_date
)
you can try this :
select data1.id,data1.Date,data1.Pricemoney from data1
left join (
select id ,min(Date) date from data1
group by id
) as t
on data1.date= t.date and t.id = data1.id
where t.id is null
group by data1.id,data1.Date,data1.Pricemoney
above query not duplicated records also ignore, if want
not duplicated records then use having count(id) > 1 in left query e,g.
select data1.id,data1.Date,data1.Pricemoney from data1
left join (
select id ,min(Date) date from data1
group by id
having COUNT(id) > 1
) as t
on data1.date= t.date and t.id = data1.id
where t.id is null
group by data1.id,data1.Date,data1.Pricemoney

get the max child job record in the same table

I have the below Job table where in we have 5 columns.
consider Job_id is primary key and parent_job_id will be null for the parent job and I have given the number values for the DATE column values
for convenience..
pls consider the below table data
JOB_ID ABC XYZ DATE PARENT_JOB_ID
1 a b 1 null
2 a b 1 1
3 a b 2 1
7 a b 3 1
4 a b 3 null
5 a b 1 4
6 a b 2 4
In this, I need to query in such a way that it should give me the below results,
JOB_ID ABC XYZ PQR PARENT_JOB_ID
1 a b 1 null
7 a b 3 1
4 a b 3 null
6 a b 2 4
they are the parent jobs + the latest child jobs only ( where the DATE value is max)
Please help/advise.
thank you
If your database supports row_number() analytic function, then one way is to get
the latest child jobs only ( where the DATE value is max)
using row_number() function.
then get parent jobs separately (... where PARENT_JOB_ID is null)
and then UNION ALL results from both queries.
Something like:
select * from (
select JOB_ID, ABC, XYZ, DATE, PARENT_JOB_ID from (
select *, row_number() over(partition by PARENT_JOB_ID order by DATE desc) rn
from your_table
where PARENT_JOB_ID is not null
) t
where rn = 1
union all
select JOB_ID, ABC, XYZ, DATE, PARENT_JOB_ID
from your_table
where PARENT_JOB_ID is null
) t
order by coalesce(PARENT_JOB_ID, JOB_ID) , JOB_ID

Query Two Different Table that have same field item

I have two table
Table_A
ID PostId Item Stock Price
1 1 A 30 10
2 1 B 40 20
3 2 A 50 5
4 3 A 50 25
Table_B
ID PostId Item_ID Sold Price
1 1 1 2 20
2 1 2 2 40
3 1 1 1 10
4 2 3 3 15
5 2 3 1 5
I want to queries from above two table that have same 'PostID' and COUNT and SUM some field group by 'PostID', expected output would be like this
Output
ID PostId Total Item Total Stock Total Buyer(s) Total Sold Total Price
1 1 2 70 3 5 70
I've try to JOIN it, but result still miss calculate
SELECT Table_A.PostId AS PostId, COUNT(Table_A.Item) AS Total_Item, SUM(Table_A.stock) AS Total_Stock, COUNT(Table_B.Item_ID) AS total_buyer, SUM( Table_B.Sold ) AS TotalSold, SUM( Table_B.Price ) AS Total_Price
FROM Table_A
LEFT JOIN Table_B
ON Table_A.PostId = Table_B.PostId
WHERE Table_A.PostId = '1'
GROUP BY Table_A.PostId
LIMIT 0 , 30
Any suggestion for this query problem?? Thank you
SELECT Table_B.PostId AS PostId,
MIN(Table_A.Total_Item) AS Total_Item,
MIN(Table_A.Total_Stock) AS Total_Stock,
COUNT(Table_B.Item_ID) AS total_buyer,
SUM( Table_B.Sold ) AS TotalSold,
SUM( Table_B.Price ) AS Total_Price
FROM Table_B
LEFT JOIN
(
SELECT PostId,
COUNT(Item) AS Total_Item,
SUM(stock) AS Total_Stock
FROM
Table_A
GROUP BY PostId
) Table_A
ON Table_B.PostId=Table_A.PostId
WHERE Table_B.PostId = '1'
GROUP BY Table_B.PostId
LIMIT 0 , 30

How to select Remain values after subtract with one Fixed value

Need To select Data From One Table After Minus With One Value
this is the question i already asked and this solution for one value input to table and result. but i need this with more input values for different categories and each categories output
for eg(based of previous question)
Table 1
SNo Amount categories
1 100 type1
2 500 type1
3 400 type1
4 100 type1
5 100 type2
6 200 type2
7 300 type2
8 500 type3
9 100 type3
and
values for type1 - 800
values for type2 - 200
values for type3 - 100
and the output need is
for type-1
800 - 100 (Record1) = 700
700 - 500 (record2) = 200
200 - 400 (record3) = -200
The table records starts from record 3 with Balance Values Balance 200
Table-Output
SNo Amount
1 200
2 100
that means if minus 800 in first table the first 2 records will be removed and in third record 200 is Balance
same operation for remain types also and how to do it?
SQLFiddle demo
with T1 as
(
select t.*,
SUM(Amount) OVER (PARTITION BY [Type] ORDER BY [SNo])
-
CASE WHEN Type='Type1' then 800
WHEN Type='Type2' then 200
WHEN Type='Type3' then 100
END as Total
from t
)select Sno,Type,
CASE WHEN Amount>Total then Total
Else Amount
end as Amount
from T1 where Total>0
order by Sno
UPD: If types are not fixed then you should create a table for them, for example:
CREATE TABLE types
([Type] varchar(5), [Value] int);
insert into types
values
('type1',800),
('type2',200),
('type3',100);
and use the following query:
with T1 as
(
select t.*,
SUM(Amount) OVER (PARTITION BY t.[Type] ORDER BY [SNo])
-
ISNULL(types.Value,0) as Total
from t
left join types on (t.type=types.type)
)select Sno,Type,
CASE WHEN Amount>Total then Total
Else Amount
end as Amount
from T1 where Total>0
order by Sno
SQLFiddle demo
UPDATE: For MSSQL 2005 just replace SUM(Amount) OVER (PARTITION BY t.[Type] ORDER BY [SNo]) with (select SUM(Amount) from t as t1
where t1.Type=t.Type
and t1.SNo<=t.SNo)
with T1 as
(
select t.*,
(select SUM(Amount) from t as t1
where t1.Type=t.Type
and t1.SNo<=t.SNo)
-
ISNULL(types.Value,0) as Total
from t
left join types on (t.type=types.type)
)select Sno,Type,
CASE WHEN Amount>Total then Total
Else Amount
end as Amount
from T1 where Total>0
order by Sno
SQLFiddle demo