Oracle - Getting the rows w/ condition of two columns having minimum values - sql

I am a newbie to PLSQL. I would like to ask for your help.
I have a table below.
Item
Week
Qty
DMD_WK
DMD_QTY
ACC_DMD
WIP
H00978A510
26
300
26
0
0
1
H00978A510
26
300
27
0
0
2
H00978A510
26
300
28
300
300
3
H00978A510
26
300
29
100
400
3
H00978A510
26
300
30
100
500
4
first of all, I want to filter the records that has QTY < ACC_DMD. so the result will be below(I'm okay w/ this part)
Item
Week
Qty
DMD_WK
DMD_QTY
ACC_DMD
WIP
H00978A510
26
300
29
100
400
3
H00978A510
26
300
30
100
500
4
then, I need to get the row having the minimum DMD_WK and also having the minimum WIP grouped by item, week and qty after the filter being applied(Need help on this part)
so that the query will result in this:
Item
Week
Qty
DMD_WK
DMD_QTY
ACC_DMD
WIP
H00978A510
26
300
29
100
400
3
Hoping for your time and help, thanks in advance.

SELECT *
FROM YOURTABLE t
WHERE
DMD_WK = (SELECT MIN(tin.DMD_WK)
FROM YOURTABLE tin
WHERE tin.ITEM = t.ITEM AND tin.QTY < tin.ACC_DMD
GROUP BY tin.ITEM )
AND WIP = (SELECT MIN(tin.WIP)
FROM YOURTABLE tin
WHERE tin.ITEM = t.ITEM AND tin.QTY < tin.ACC_DMD
GROUP BY tin.ITEM )

Related

Gaps and Islands with continuous ranges from previous row

I have the following set of Data
SET
START
END
QTY
A
1
10
10
A
11
20
10
A
21
30
10
B
51
60
10
B
61
70
10
B
81
90
10
B
91
100
10
C
101
200
100
C
201
300
100
C
401
500
100
And wanted to have the following result:
SET
START
END
TOTAL_QTY
A
1
30
30
B
51
70
20
B
81
100
20
C
101
300
200
C
401
500
100
So it will check previous "End" range and if it's a continuous from the previous "Start" range then it will be grouped into one "Start - End" ranges with the Sum of Qty.
I don't know how this can be achieved with Oracle SQL, can anyone help?
select "SET"
,min("START") as "START"
,max("END") as "END"
,sum(QTY) as QTY
from (
select t.*
,count(mrk) over(partition by "SET" order by "START") as grp
from (
select t.*
,case when "START" - lag("END") over(partition by "SET" order by "START") > 1 then 1 end as mrk
from t
) t
) t
group by "SET", grp
SET
START
END
QTY
A
1
30
30
B
51
70
20
B
81
100
20
C
101
300
200
C
401
500
100
Fiddle

How can I transfer the data from on column to another based on another column values in SQL

select Products, Fiscal_year, Fiscal_Period, Stock_QTY, DaysRemaining,
(Stock_QTY / DaysRemaining) as QtyforPeriod,
Stock_QTY -(Stock_QTY / DaysRemaining) as LeftforNextmonth
from Stocks
products| Fiscal_yaer| Fiscal_period| Stock_QTY |DaysReamain| QtyforPeriod |LeftforNextMonth
5000 22 1 100 4
6000 22 1 200 4
7000 22 2 300 20
7000 22 3 400 40
8000 23 1 500 60
5000 23 1 600 60
7000 23 2 700 90
8000 23 3 800 100
There is any possibility to write a query if the Fiscal_yae =22 Fiscal_period=4. Subtract StockTY - LeftforNextMonth of period 3 and divided by DaysRemaining.
Like if the Fiscal_yae =22 Fiscal_period=5. Subtract StockTY - LeftforNextMonth of period 4 and divided by days remaining.
Like if the Fiscal_yae =22 Fiscal_period=6. Subtract StockTY ( - ) LeftforNextMonth of period 5 and divided by days remaining.

Properly 'Joining' two Cross Applies

I've got a query with three Cross-Applies that gather data from three different tables. The first Cr-Ap assists the 2nd and 3rd Cr-Ap's. It finds the most recent ID of a certain refill for a 'cartridge', the higher the ID the more recent the refill.
The second and third Cr-Ap's gather the SUMS of items that have been refilled and items that have been dispensed under the most recent Refill.
If I run the query for Cr-Ap 2 or 3 separately the output would look something like:
ID Amount
1 100
2 1000
3 100
4 0
5 0
etc
Amount would be either the amount of dispensed or refilled items.
Only I don't want to run these queries separately, I want them next to each other.
So what I want is a table that looks like this:
ID Refill Dispense
1 100 1
2 1000 5
3 100 7
4 0 99
5 0 3
etc
My gut tells me to do
INNER JOIN crossaply2 ON crossapply3.ID = crossapply2.ID
But this doesn't work. I'm still new to SQL so I don't exactly know what I can and can't join, what I do know is that you can use crossapply as a join (sorta?). I think that might be what I need to do here, I just don't know how.
But that's not it, there's another complication, there are certain refills where nothing gets dispensed. In these scenarios the crossapply I wrote for dispenses won't return anything for that refillID. With nothing I don't mean NULL, I mean it just skips the refillID. But I'd like to see a 0 in those cases. Because it just skips over those ID's I can't get COALESCE or ISNULL to work, this might also complicate the joining of these two applies. Because an INNER JOIN would skip any line where there is no Dispensed amount, even though there is a Refilled amount Id like to see.
Here is my code:
-- Dispensed SUM and Refilled SUM combined
SELECT [CartridgeRefill].[FK_CartridgeRegistration_Id]
,Refills.Refilled
,Dispenses.Dispensed
FROM [CartridgeRefill]
CROSS APPLY(
SELECT MAX([CartridgeRefill].[Id]) AS RecentRefillID
FROM [CartridgeRefill]
GROUP BY [CartridgeRefill].[FK_CartridgeRegistration_Id]
) AS RecentRefill
CROSS APPLY(
SELECT [CartridgeRefill].[FK_CartridgeRegistration_Id] AS RefilledID
,SUM([CartridgeRefillMedication].[Amount]) AS Refilled
FROM [CartridgeRefillMedication]
INNER JOIN [CartridgeRefill] ON [CartridgeRefillMedication].[FK_CartridgeRefill_Id] = [CartridgeRefill].[Id]
WHERE [CartridgeRefillMedication].[FK_CartridgeRefill_Id] = RecentRefill.RecentRefillID
GROUP BY [CartridgeRefill].[FK_CartridgeRegistration_Id]
) AS Refills
CROSS APPLY(
SELECT [CartridgeRefill].[FK_CartridgeRegistration_Id] AS DispensedID
,SUM([CartridgeDispenseAttempt].[Amount]) AS Dispensed
FROM [CartridgeDispenseAttempt]
INNER JOIN [CartridgeRefill] ON [CartridgeDispenseAttempt].[FK_CartridgeRefill_Id] = [CartridgeRefill].[Id]
WHERE [CartridgeDispenseAttempt].[FK_CartridgeRefill_Id] = RecentRefill.RecentRefillID
GROUP BY [CartridgeRefill].[FK_CartridgeRegistration_Id]
) AS Dispenses
GO
The output of this code is as follows:
1 300 1
1 300 1
1 200 194
1 200 194
1 200 8
1 200 8
1 0 39
1 0 39
1 100 14
1 100 14
1 200 1
1 200 1
1 0 28
1 0 28
1 1000 102
1 1000 102
1 1000 557
1 1000 557
1 2000 92
1 2000 92
1 100 75
1 100 75
1 100 100
1 100 100
1 100 51
1 100 51
1 600 28
1 600 28
1 200 47
1 200 47
1 200 152
1 200 152
1 234 26
1 234 26
1 0 227
1 0 227
1 10 6
1 10 6
1 300 86
1 300 86
1 0 194
1 0 194
1 500 18
1 500 18
1 1000 51
1 1000 51
1 1000 56
1 1000 56
1 500 48
1 500 48
1 0 10
1 0 10
1 1500 111
1 1500 111
1 56 79
1 56 79
1 100 6
1 100 6
1 44 134
1 44 134
1 1000 488
1 1000 488
1 100 32
1 100 32
1 100 178
1 100 178
1 500 672
1 500 672
1 200 26
1 200 26
1 500 373
1 500 373
1 100 10
1 100 10
1 900 28
1 900 28
2 900 28
2 900 28
2 900 28
etc
It is total nonsense that I can't do much with, it goes on for about 20k lines and goes through all the ID's, eventually.
Any help is more than appreciated :)
Looks like overcomplicated a bit.
Try
WITH cr AS (
SELECT [FK_CartridgeRegistration_Id]
,MAX([CartridgeRefill].[Id]) RecentRefillID
FROM [CartridgeRefill]
GROUP BY [FK_CartridgeRegistration_Id]
)
SELECT cr.[FK_CartridgeRegistration_Id], Refills.Refilled, Dispenses.Dispensed
FROM cr
CROSS APPLY(
SELECT SUM(crm.[Amount]) AS Refilled
FROM [CartridgeRefillMedication] crm
WHERE crm.[FK_CartridgeRefill_Id] = cr.RecentRefillID
) AS Refills
CROSS APPLY(
SELECT SUM(cda.[Amount]) AS Dispensed
FROM [CartridgeDispenseAttempt] cda
WHERE cda.[FK_CartridgeRefill_Id] = cr.RecentRefillID
) AS Dispenses;

SQL Method to report next period value for this period

This may already be answered, but I can't figure out the correct search terms for what I need. We store values by Year / Period for the Beginning of Month (BOM). The BOM for one month is the same value as End of Month (EOM) for the previous month. I need a way to report this as such.
So 2018-02 BOM = 2018-01 EOM.
I thought I might be able to use something simple, but it does not account for the month/year wrap at 12 months as those fields are numerical.
select yr as YEAR, (pd-1) as PERIOD, sum(BOM) as EOM
from Table1
where type = '3'
group by yr, pd
order by yr desc, pd desc
This works for the middle months, but not for January, which becomes 2018-0 instead of 2017-12.
Example Data
Yr Pd Type BOM
18 02 3 100
18 02 3 100
18 02 2 200
18 02 2 100
18 01 3 100
18 01 3 100
18 01 2 200
18 01 2 100
18 01 3 100
18 01 2 300
17 12 3 100
17 12 3 200
17 12 2 300
17 12 3 200
17 12 2 100
17 11 3 300
17 11 2 400
17 11 3 400
17 11 2 100
So the results I am looking for would be:
Yr Pd EOM
18 01 200
17 12 300
17 11 500
17 10 700
I'm working in System iNavigator currently, but hoping to move this into an externally connected Excel query at some point.
Your DB2 database should be able to use CASE WHEN
Which can be used to calculate the year and the month, depending on the month.
For example:
select
CASE WHEN pd = 1 THEN yr - 1 ELSE yr END as Yr,
CASE WHEN pd = 1 THEN 12 ELSE pd - 1 END as Pd,
SUM(BOM) as EOM
from Table1
where type = '3'
group by yr, pd
order by yr desc, pd desc

Enumerate records in table on multiple columns

ID descr points
----------------------
1000 24 100
1000 24 40
1000 25 100
1000 25 40
2000 24 100
2000 25 100
2000 26 100
Above is my table. I want to add/update column enumerating records on basis of ID and descr. How can I do that?
Below is the result I am looking for.
ID descr points order#
-------------------------------
1000 24 100 1
1000 24 40 2
1000 25 100 1
1000 25 40 2
2000 24 100 1
2000 25 100 2
2000 26 100 3
You can use the ANSI standard function `row_number():
select id, descr, points,
row_number() over (partition by id, descr order by points desc) as ordernum
from t;