Fifo Inventory with SQL - sql

I need one adaptation for the first table because there are negative issues points and I need the net table considerating the negatives points as debit of the first time of issue. E.g:
FechaEmi Cuenta PtosEmi PtosCan
30/06/2015 1 100 0
31/07/2015 1 120 0
31/08/2015 1 130 0
31/08/2015 1 0 55
30/09/2015 1 50 0
31/10/2015 1 30 0
30/11/2015 1 70 0
31/12/2015 1 95 0
31/01/2016 1 50 0
29/02/2016 1 0 74
31/03/2016 1 50 0
30/04/2016 1 15 0
30/06/2015 2 20 0
31/07/2015 2 30 0
31/08/2015 2 40 0
30/09/2015 2 350 0
30/06/2015 3 150 0
31/07/2015 3 120 0
31/08/2015 3 0 56
31/08/2015 3 220 0
30/06/2015 4 70 0
31/07/2015 4 134 0
31/08/2015 4 12 0
30/06/2015 5 97 0
31/07/2015 5 130 0
31/08/2015 5 15 0
30/09/2015 5 135 0
31/10/2015 5 20 0
30/11/2015 5 140 0
31/12/2015 5 25 0
31/01/2016 5 145 0
29/02/2016 5 0 25
where:
FechaEmi= Date;
Cuenta=ID;
PtosEmi=Issues points;
PtosCan=Canceled points
I want this table
FechaEmi Cuenta PtosEmi
30/06/2015 1 0
31/07/2015 1 91
31/08/2015 1 130
30/09/2015 1 50
31/10/2015 1 30
30/11/2015 1 70
31/12/2015 1 95
31/01/2016 1 50
31/03/2016 1 50
30/04/2016 1 15
30/06/2015 2 20
31/07/2015 2 30
31/08/2015 2 40
30/09/2015 2 350
30/06/2015 3 94
31/07/2015 3 120
31/08/2015 3 220
30/06/2015 4 70
31/07/2015 4 134
31/08/2015 4 12
30/06/2015 5 72
31/07/2015 5 130
31/08/2015 5 15
30/09/2015 5 135
31/10/2015 5 20
30/11/2015 5 140
31/12/2015 5 25
31/01/2016 5 145
I have this code. The problem is that doesn't do anything with the points that were debited in a date that there are not issues point. How can you recommend me change that query? Thanks!
with cte as(
select Fechaemi, Cuenta,PtosEmi,PtosCan
,row_number() over (partition by Fechaemi,Cuenta order by Fechaemi,Cuenta) as rank
from emision)
select a.Fechaemi, a.Cuenta,a.PtosEmi - coalesce(b.PtosCan, 0) stock
from cte a
left join cte b on
a.FechaEmi= b.FechaEmi and a.Cuenta = b.Cuenta and a.rank = b.rank - 1
where a.PtosEmi - coalesce(b.PtosCan, 0) > 0 order by a.cuenta asc, a.fechaemi asc

SQL FIDDLE DEMO
with totalPay as(
SELECT Cuenta, SUM(PtosCan) TotalPayment
FROM emision
GROUP BY Cuenta
),
totalDebt as (
SELECT FechaEmi, Cuenta, (SELECT SUM(PtosEmi)
FROM emision e2
WHERE e2.FechaEmi <= e.FechaEmi
AND e2.Cuenta = e.Cuenta
) AS TotalDebt
FROM emision e
WHERE e.PtosEmi <> 0
)
select
e.FechaEmi,
e.Cuenta,
e.PtosEmi,
td.TotalDebt,
tp.TotalPayment,
CASE
WHEN td.TotalDebt < tp.TotalPayment THEN 0
WHEN td.TotalDebt - tp.TotalPayment > PtosEmi THEN PtosEmi
ELSE td.TotalDebt - tp.TotalPayment
END Remaining
FROM
totalDebt td inner join
totalPay tp on td.Cuenta = tp.Cuenta inner join
emision e on td.FechaEmi = e.FechaEmi AND td.Cuenta = e.Cuenta
WHERE
e.PtosEmi <> 0

Possibly not the most elegant, but explicit way:
WITH
PtosEmi AS(
SELECT FechaEmi, cuenta, SUM(PtosEmi) as PtosEmi
FROM table1
GROUP BY FechaEmi, cuenta),
PtosCan AS (
SELECT MIN(FechaEmi) as FechaEmi, cuenta, SUM(PtosCan) as PtosCan
FROM table1
GROUP BY cuenta)
SELECT
e.FechaEmi,
e.cuenta,
e.ptosemi,
c.ptoscan,
e.ptosemi - COALESCE(c.ptoscan, 0) total
FROM
PtosEmi e LEFT JOIN
PtosCan c ON e.FechaEmi = c.FechaEmi AND e.cuenta = c.cuenta
ORDER BY e.cuenta, e.FechaEmi
This is based on the assumption that you cannot have cancellations before anything was issued for give cuenta.
Also if you have more cancelled items in total compared to what was issued initially, total value will be negative.
http://sqlfiddle.com/#!6/9ac40/11
Update
as you want to reduce cancellations line by line here is updated query:
WITH
ptosemi AS(
SELECT FechaEmi, cuenta,
PtosEmi as PtosEmi,
SUM(PtosEmi) OVER (PARTITION BY cuenta ORDER BY FechaEmi) runsum
FROM table1),
PtosCan AS (
SELECT cuenta, SUM(PtosCan) as PtosCan
FROM table1
GROUP BY cuenta)
SELECT
e.FechaEmi,
e.cuenta,
e.ptosemi,
e.runsum,
c.ptoscan,
CASE
WHEN e.runsum <= c.ptoscan
THEN 0
WHEN c.ptoscan BETWEEN e.runsum - e.ptosemi AND e.runsum
THEN e.runsum - COALESCE(c.ptoscan, 0)
ELSE e.ptosemi END total
FROM
ptosemi e LEFT JOIN
PtosCan c ON e.cuenta = c.cuenta
ORDER BY e.cuenta, e.FechaEmi
http://sqlfiddle.com/#!6/8036c2/25

Related

Getting Complex Result With Balance

I have the two tables Issue and Received. I want to get result with same row of issue.
Issue table:
NO
LCODE
PCS
1
L0001
10
2
L0002
25
3
L0003
75
4
L0004
12
5
L0005
15
Received table:
NO
LCODE
PCS
1
L0001
5
2
L0001
5
3
L0003
48
4
L0003
12
5
L0003
15
Wanted result:
NO
LCODE
ISSPCS
RECPCS
BAL
1
L0001
10
5
5
2
L0001
0
5
0
3
L0003
75
48
27
4
L0003
0
12
15
5
L0003
0
15
0
6
L0004
12
0
12
7
L0005
15
0
15
SELECT ROW_NUMBER() OVER(PARTITION BY i.LCODE ORDER BY i.LCODE) as NO,
i.LCODE,i.PCS as ISSPCS,r.PCS as RECPCS,(i.PCS-r.PCS) as BAL
FROM Issue i
LEFT JOIN Received r ON i.LCODE = r.LCODE
Find The Best Way To Getting This Result Thank you.
Try this code:
SELECT ROW_NUMBER() OVER ( ORDER BY i.LCODE ASC, RunninngSum ASC) AS [NO]
, i.LCODE
, CASE WHEN RunninngSum > r.PCS THEN 0 ELSE i.PCS
END AS ISSPCS
, ISNULL( r.PCS, 0) AS RECPCS
, i.PCS - ISNULL( RunninngSum, 0) as BAL
FROM Issue i
LEFT JOIN Received r ON i.LCODE = r.LCODE
CROSS APPLY (
SELECT SUM( r1.PCS) AS RunninngSum
FROM Received r1
WHERE r1.LCODE = r.LCODE AND r1.[NO] <= r.[NO]
)x

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;

Count and SUM using case

I have table like this, name: Table.dbo
Amount Desc Month SM code ID
$32,323.00 Bla1 1 121 3 2424221
$4,242.00 Bla2 1 A1 3 2424221
$3,535.00 Bla3 1 A3 1 3230824
$4,984.00 Bla4 1 433 1 3230824
$47,984.00 Bla5 1 B1 1 3230824
$3,472.00 Bla6 1 D2 27 2297429
$3,239.00 Bla7 1 124 27 2297429
$4,249.00 Bla8 1 114 24 3434334
$2,492.00 Bla9 1 132 24 3434334
$424.00 Bla10 2 232 3 2424221
$24,242.00 Bla7 2 124 3 2424221
$242,424 Bla4 2 433 1 3230824
$533.00 Bla13 2 235 1 3230824
$4,342.00 Bla14 2 223 1 3230824
$24,242.00 Bla15 2 224 27 2297429
$24,242.00 Bla1 2 121 27 2297429
$4,242.00 Bla17 2 432 24 3434334
$24,224.00 Bla9 2 132 24 3434334
I wrote this query :
select
[SM],
count(*) as TotalCntOfSM,
sum(case when [code] between 4 and 27 then 1 else 0 end) as TotalCntOfSM_R,
sum(case when [code] in (1,2,3) then 1 else 0 end) as TotalCntOfSM_B,
sum(case when [code] in (1) then 1 else 0 end) as TotalCntofSM_B1,
sum(case when [code] in (2) then 1 else 0 end) as TotalCntofSM_B2,
sum(case when [code] in (3) then 1 else 0 end) as TotalCntofSM_B3,
sum([Amount]) As TotalAmount
****[How can I sum the Amount for the SM if the code is between 4 and 27?** For example]**
from [Table]
group by [SM]
order by TotalCntOfSM desc
How can I sum the Amount for the SM if the code is between 4 and 27 or the code is in (1,2,3) only (For example).
Thank you very much!
Exactly like qxg said - Replace
****[How can I sum the Amount for the SM if the code is between 4 and 27?** For example]** `
with
sum(case when [code] between 4 and 27 then [Amount] else 0 end) as SMAmount
If you want to total up amount for code between 4 and 27 or for codes 1,2,3
sum(case when [code] between 1 and 27 then [Amount] else 0 end) as SMAmount
You can write the above also as
sum(case when [code] between 4 and 27 OR [code] in (1,2,3) then [Amount] else 0 end) as SMAmount

SQL LOGIC using 3conditions

course_completions CC
id coursemodid userid state timemodified
370 23 2 1 1433582890
329 24 89 1 1427771915
333 30 39 1 1428309816
332 32 39 1 1428303307
327 33 40 1 1427689703
328 34 89 1 1427710711
303 35 41 1 1410258482
358 36 99 1 1432020067
365 25 2 1 1433142455
304 26 69 1 1410717866
353 37 95 1 1430387005
416 38 2 1 1438972465
300 27 70 1 1409824001
302 29 74 1 1412055704
297 30 2 1 1409582123
301 133 41 1 1410255923
336 133 91 1 1428398435
364 133 40 1 1433142348
312 133 85 1 1425863621
course_modules CM
id course
23 6
24 6
25 6
26 6
27 6
28 6
29 8
30 8
31 8
32 8
33 8
34 5
35 5
36 5
37 5
38 5
39 9
40 9
41 9
course_mod_settings CMS
id course modinstance
27 8 30
28 8 31
29 8 32
30 8 33
31 6 23
32 6 24
33 6 25
34 6 26
35 6 27
36 6 28
37 9 39
38 9 40
39 9 41
I need the count of each user has Completed modules, Inprocess modules and Notstarted modules for each course, where getting the count of userids from table CC by taking courseia from table CM, get number of modules that an user has completed from each course.
(A course can have morethan one module and a course can have number of users attempted all modules, few modules or not attempted at all).
So, I need number of users - has done number of modules - in a course. (3 logics)
Completed.Users means : If number of modules attempted is equal to number of modinstance from table CMS (ex: no. of modules attempted by a user per course= 9, no.modinstance = 9. Because 7 is not equal to 9, They are completed.)
Inprocess.Users means : Number of modules attempted should be >0, but not equal to [count(modinstance) per course] (ex: no. of modules attempted by a user per course= 7 , no.modinstance = 9. Because 7 is not equal to 9, They are Inprocess.)
Notstarted.Users means : Number of modules attempted should be equal to 0, (ex: no. of modules attempted by a user per course= 0. They are Notstarted).
OUTPUT :
Course No.Completed.Users No.Inprocess.Users No.Notstarted.Users
5 65 32 6
6 40 12 15
8 43 56 0
9 0 7 9
Sir, this is a very critical logic that I was trying, I couldn't get a solution. I hope stackoverflow developers could help me out. I tried with my query :
SELECT cm.course AS "Course",
(CASE WHEN
(SELECT count(cms.id) FROM course_mod_settings cms) =
(SELECT count(cmc.coursemodid) FROM course_completions cc JOIN course_modules cm ON cmc.coursemodid = cm.id WHERE cmc.state=1 )
THEN COUNT(SELECT count(cmc.coursemodid) FROM course_completions cc JOIN course_modules cm ON cmc.coursemodid = cm.id WHERE cmc.state=1 ) END) AS "No.Completed.Users",
(CASE WHEN
(SELECT count(cms.id) FROM course_mod_settings cms) > 0 AND
(SELECT count(cms.id) FROM course_mod_settings cms) !=
(SELECT count(cmc.coursemodid) FROM course_completions cc JOIN course_modules cm ON cmc.coursemodid = cm.id WHERE cmc.state=1 )
THEN COUNT(SELECT count(cmc.coursemodid) FROM course_completions cc JOIN course_modules cm ON cmc.coursemodid = cm.id WHERE cmc.state=1 ) END) AS "No.Inprocess.Users",
(CASE WHEN
(SELECT count(cms.id) FROM course_mod_settings cms) = 0
THEN COUNT(SELECT count(cmc.coursemodid) FROM course_completions cc JOIN course_modules cm ON cmc.coursemodid = cm.id WHERE cmc.state=1 ) END) AS "No.Notstarted.Users"
FROM
mdl_course c
GROUP BY c.id
SQL Fiddle
SELECT course AS "Course",
SUM(CASE WHEN completion_count = module_count THEN 1 ELSE 0 END) AS "No.Completed.Users",
SUM(CASE WHEN completion_count > 0 AND completion_count < module_count THEN 1 ELSE 0 END) AS "No.Inprocess.Users",
SUM(CASE WHEN completion_count = 0 THEN 1 ELSE 0 END) AS "No.Notstarted.Users"
FROM (SELECT course, COUNT(*) AS module_count
FROM course_modules cm
GROUP BY course) course_module_counts JOIN
(SELECT cm.course AS courseid, users.id AS userid, SUM(CASE WHEN cc.state = 1 THEN 1 ELSE 0 END) completion_count
FROM ((SELECT DISTINCT userid AS id FROM course_completions) users CROSS JOIN course_modules cm) LEFT JOIN course_completions cc ON users.id = cc.userid AND cc.coursemodid = cm.id
GROUP BY cm.course, users.id) course_completion_counts
ON course_module_counts.course = course_completion_counts.courseid
GROUP BY course
gives this output, which matches the limited dataset that you provided in your question.
| course | No.Completed.Users | No.Inprocess.Users | No.Notstarted.Users |
|--------|--------------------|--------------------|---------------------|
| 5 | 0 | 5 | 7 |
| 6 | 0 | 4 | 8 |
| 8 | 0 | 4 | 8 |
| 9 | 0 | 0 | 12 |

SQL How to group a table with special condition and join to another table

i have Table PRICE
CodePrice CodeClient TheZone Tempo W_Begin W_End Price
A_0_49 88989 1 1 0 49 20
A_50_99 60000 1 1 50 99 10
B_0_49 88989 2 1 0 49 30
C_0_49 50000 3 4 0 49 40
Table Ordre
NoID CodeClient Cp Agence TheZone Tempo Weight
01 88989 44 bidon 1 1 12
02 60000 49 toto 2 2 10
03 60000 49 bigoi 1 1 56
04 88989 49 titi 3 3 8
05 50000 44 bidon 1 1 5
How can i show the result like this:
CodePrice TheZone Tempo W_Begin W_End SUm_Weight SUM_Price CountIDOrdre CP Agence
A_0_49 1 1 0 49 17 40 2 44 bidon
A_50_99 1 1 50 99 56 10 1 49 bigoi
B_0_49 2 1 0 49 0 0 0 null null
C_0_49 3 4 0 49 0 0 0 null null
in 1 SQL Syntax (1 Step).
Nowdays i make it in 2 step
SELECT CodePrice
,CodeClient
,TheZone
,Tempo
,W_Begin
,W_End
,Price
FROM PRICE
LEFT JOIN T_TARIF_ZONE ON PRICE.ZONE = T_TARIF_ZONE.NO_ID
LEFT JOIN CLIENT ON PRICE.CodeClient= CLIENT.CODE_CL
WHERE CodeClient= #NO_CLIENT AND TheZone = #ZONE AND UNITE = #UNITE
AND (Tempo IN (SELECT ParsedString From dbo.ParseStringList(#ModLiv)))
ORDER BY MONTANT
after i select the price, now i can group the ordre on each price depends on Weight, zone, and another variable
SELECT count(NoID) as LVId
,sum(Weight)as Tot_Poids
,sum(Price) as Tot_Prix
FROM [Ordre]
WHERE Weight>= #TR_DEB AND Weight<= #TR_FIN AND LE_ZONE = #LE_ZONE AND ENLEV_UNITE = #ENLEV_UNITE
AND DATE_CLOTURE >= #Date_Deb AND DATE_CLOTURE <= #Date_Fin AND STATUT_LV = 2 AND FACTURATION = #FACTURATION
HAVING count([NOID]) > 0