Count and SUM using case - sql

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

Related

SQL show UserCode from the highest value in column

I am making a select from a table that has alums, but those alums can have a "level" being 01, 02, 03, 04, 05 or 99 and if I select a distinct(code) there will be 2 or 3 files of the same "code" with different "level". I want to be able to ONLY get the "code" with the higher "level" anytime.
Example of my code:
select
Level,
count(Code) as Atendee,
count(CASE WHEN CodPlace = 01 THEN (Atendee) ELSE null END ) as AtendeeCho,
count(CASE WHEN CodPlace = 02 THEN (Atendee) ELSE null END ) as AtendeeSB,
count(CASE WHEN CodPlace = 14 THEN (Atendee) ELSE null END ) as AtendeeIca
from #TempoPar
group by Level
order by Level
And here is the result:
Level Atendee AtendeeCho AtendeeSB AtendeeIca
1 3 2 0 1
2 0 0 0 0
3 2 2 0 0
99 1 1 0 0
Problem is that the one who is in AtendeeCho from level 1, 2 and 99 is the same person and he should only be on 99 or 3 if he wasn't on 99.
Thanks in advance!
Data example:
Code ( user) Level Career CodPlace
12345 1 9 01
12345 3 15 01
12346 1 10 14
12347 1 10 01
12345 3 15 01
12347 99 15 01
Now, this is what I require:
From the data sample:
Code ( user) Level Career CodPlace
12345 3 15 01
12346 1 10 14
12347 99 15 01
In the final output with the corrected data it should be:
Level Atendee AtendeeCho AtendeeSB AtendeeIca
1 1 0 0 1
2 0 0 0 0
3 1 1 0 0
99 1 1 0 0

SQL aggregation query and sum columns

I have this table (I put the name over needed colums)
iddip date idv idc val
47 2018-06-01 00:00:00.000 0 3 3 60 NULL NULL
47 2018-06-01 00:00:00.000 0 1 3 200 NULL NULL
47 2018-06-01 00:00:00.000 0 1 4 280 NULL NULL
43 2018-06-01 00:00:00.000 0 3 2 510 NULL NULL
53 2018-06-01 00:00:00.000 0 1 4 480 NULL NULL
29 2018-06-01 00:00:00.000 0 3 2 510 NULL NULL
2 2018-06-11 00:00:00.000 0 1 2 480 NULL NULL
47 2018-06-02 00:00:00.000 0 1 3 100 NULL NULL
I want to obtain this:
id idc Totidv1 Totidv3 TOT
47 3 300 60 360
47 4 280 0 280
43 2 0 510 510
53 4 480 0 480
29 2 0 510 510
2 2 480 0 480
The closest I can get is:
SELECT DISTINCT(iddip),IDCENTROCOSTO,tot=SUM(VALORE),ord=( SELECT SUM(isnull(VALORE,0)) FROM VALORIVOCICDC WHERE IDVOCE='1' and iddip=v.IDDIP and IDCENTROCOSTO ='3' GROUP BY iddip,IDCENTROCOSTO),
str=( SELECT SUM(isnull(VALORE,0)) FROM VALORIVOCICDC WHERE IDVOCE='3' and iddip=v.IDDIP and IDCENTROCOSTO ='3' GROUP BY iddip,IDCENTROCOSTO)
FROM VALORIVOCICDC v
GROUP BY v.iddip,IDCENTROCOSTO
But it returns wrong sums in totidv1 and totisv3, How can I do this? Thanks for any hint
You just need a GROUP BY here (not distinct) and a couple of CASE statements:
SELECT
id,
idc,
SUM(CASE WHEN idv=3 THEN idv ELSE 0 END) as totidv1,
SUM(CASE WHEN idv=1 THEN idv ELSE 0 END) as totidv3,
SUM(idv) as Tot
FROM yourtable
GROUP BY id, idc
Note that Distinct is not a function that you can call like SELECT DISTINCT(somecolumn) This is functionally equivalent to SELECT DISTINCT somecolumn... in that it works against the entire record set returned by the SELECT statement either way.

Find duplicates on multiple columns in a SQL

I want to find the batchID who are having subjectID(0,1,2) only, pls help me, thanks in advance
I need answer BatchID=12 and BatchID=51, what can I do in sql
MyTable
uid BatchID SubjectID
6 2 0
7 2 1
8 2 2
9 2 4
10 3 0
11 3 1
12 4 5
13 4 0
14 5 5
15 6 5
17 7 0
18 7 1
19 7 2
26 12 0
27 12 1
28 12 2
29 1 0
30 1 1
31 1 4
62 45 5
63 46 0
64 46 1
65 46 4
107 49 6
108 49 2
109 49 4
110 50 1
111 50 3
116 0 1
117 0 4
118 51 0
119 51 1
120 51 2
You can use conditional aggregation for this:
select batchId
from your_table
group by batchId
having count(distinct case when subjectID in (0,1,2) then subjectID end) = 3
and count(case when subjectID not in (0,1,2) then 1 end) = 0
Explanation:
Group by batchId - Aggregate on batchId
count(distinct case when subjectID in (0,1,2) then subjectID end) - Produces 3 only if all three of them are present for this batchId
count(case when subjectID not in (0,1,2) then 1 end) - Produces 0 if there is no other subjectID except 0,1,2 assuming nulls are not allowed in the subjectId column.
You can use Row_Number()
;with cte as (
select *, RowN = row_number() over (partition by batchid order by uid) from #yourbatch where subjectid in (0,1,2)
) select distinct BatchId from cte where RowN > 1

Fifo Inventory with 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

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