Transpose the problem table into result table and calculate the drop in sales amount from one quarter to previous quarter. Rank them on the basis of total drop for a person (total drop is sum of column I for a person).
📌 Challenge Details and Links
ExcelBI Power Query Challenge Number: 239
Challenge Difficulty: ⭐️⭐️
📥Download Sample File
📥Link to the solutions on LinkedIn
Solving the challenge of Rank Sales Drop Per Person with Power Query
Power Query solution 1 for Rank Sales Drop Per Person, proposed by Zoran Milokanović:
let
Source = Excel.CurrentWorkbook(){[Name = "Input"]}[Content],
H = Table.ColumnNames(Source),
P = Table.TransformRows(
Source,
each
let
d = {[Q2] - [Q1], [Q3] - [Q2], [Q4] - [Q3]}
in
{[Name], List.Sum(d)} & d
),
S = Table.FromRows(
List.TransformMany(
P,
each List.Zip({{2, 3, 4}, List.LastN(_, 3)}),
(i, _) =>
let
f = Byte.From(_{0} = 2)
in
{
{null, i{0}}{f},
H{_{0}} & "-" & H{_{0} - 1},
_{1},
{null, List.PositionOf(List.Sort(List.Distinct(List.Zip(P){1}), 1), i{1}) + 1}{f}
}
),
{"Name", "QtQ Drop", "Amount", "Rank"}
)
in
S
Power Query solution 2 for Rank Sales Drop Per Person, proposed by Kris Jaganah:
let
A = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content],
B = Table.UnpivotOtherColumns(A, {"Name"}, "A", "V"),
C = Table.Combine(
Table.Group(
B,
{"Name"},
{
"All",
each
let
a = List.Positions([V]),
b = List.Skip(List.Transform(a, (x) => [V]{x} - [V]{x - 1})),
c = List.Skip(List.Transform(a, (y) => [A]{y} & "-" & [A]{y - 1})),
d = Table.FromList(
List.Positions(c),
(z) => {[Name]{0}, c{z}, b{z}, List.Sum(b)},
{"Name", "QtQ Drop", "Amount", "Sum"}
)
in
d
}
)[All]
),
D = Table.AddColumn(
C,
"Rank",
each Table.RowCount(A) - List.PositionOf(List.Distinct(C[Sum]), [Sum]) - 1
),
E = Table.TransformRows(
D,
(v) =>
let
p =
if v[QtQ Drop] <> "Q2-Q1" then
Record.TransformFields(v, {{"Name", each null}, {"Rank", each null}})
else
v,
q = Record.RemoveFields(p, {"Sum"})
in
q
),
F = Table.FromRecords(E)
in
F
Power Query solution 3 for Rank Sales Drop Per Person, proposed by Alejandro Simón 🇵🇦 🇪🇸:
let
Source = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content],
Unpivot = Table.UnpivotOtherColumns(Source, {"Name"}, "A", "V"),
Fx = (x) => List.Transform({1 .. List.Count(x[V]) - 1}, each x[V]{_} - x[V]{_ - 1}),
Fy = each List.Count(List.Select(_, (x) => x < 0)),
Group = Table.Group(
Unpivot,
{"Name"},
{
{"C", each Fy(Fx(_))},
{
"B",
each
let
a = _,
b = Fx(a),
c = List.Zip({List.Skip(a[A]), List.RemoveLastN(a[A])}),
d = List.Transform(c, each Text.Combine(_, "-")),
e = Fy(b),
f = Table.FromRows(
List.Zip({{a[Name]{0}}, d, b, {e}}),
{"Name", "QtQ Drop", "Amount", "Rank"}
)
in
f
}
}
),
Sol = Table.Combine(Table.Sort(Group, {{"C", 1}})[B])
in
Sol
Power Query solution 4 for Rank Sales Drop Per Person, proposed by Luan Rodrigues:
let
Fonte = Tabela1,
cab = List.Transform(
{0 .. 2},
each {"Name"} & List.Reverse(List.Range(List.Skip(Table.ColumnNames(Fonte)), _, 2))
),
trf = List.Transform(
{0 .. 2},
each
let
a = Table.SelectColumns(Fonte, cab{_}),
b = Table.AddColumn(
Table.DemoteHeaders(a),
"tab",
each [
QtQ Drop = Text.Combine(List.Skip(Table.ColumnNames(a)), "-"),
Amount = [Column2] - [Column3]
]
)
in
b
),
cmb = Table.Combine(trf),
exp = Table.ExpandRecordColumn(cmb, "tab", Record.FieldNames(cmb[tab]{0})),
err = Table.RemoveRowsWithErrors(exp, {"Amount"})[[Column1], [QtQ Drop], [Amount]],
grp = Table.AddRankColumn(
Table.Group(err, {"Column1"}, {{"tab", each _}, {"Queda", each List.Sum(_[Amount])}}),
"Rank",
{"Queda", 1}
),
expo = Table.ExpandTableColumn(grp, "tab", List.Skip(Table.ColumnNames(grp[tab]{0}))),
cls = Table.Sort(expo, {each List.PositionOf(Fonte[Name], [Column1])}),
rst = Table.ReplaceValue(
cls,
each [QtQ Drop],
null,
(a, b, c) => if not Text.StartsWith(b, "Q2") then c else a,
{"Column1", "Rank"}
),
rem = Table.RemoveColumns(rst, {"Queda"}),
ren = Table.RenameColumns(rem, {{"Column1", "Name"}})
in
ren
Power Query solution 5 for Rank Sales Drop Per Person, proposed by Abdallah Ally:
let
Source = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content],
AddCol1 = Table.AddColumn(
Source,
"Data",
each [
a = List.Skip(Record.ToList(_)),
b = List.Skip(a),
c = List.RemoveLastN(a, 1),
d = List.Zip({b, c}),
e = List.Transform(d, each _{0} - _{1}),
f = [D = e, T = List.Sum(e)]
][f]
),
Expand = Table.ExpandRecordColumn(AddCol1, "Data", {"D", "T"}),
AddCol2 = Table.AddColumn(Expand, "Rank", each List.PositionOf(List.Sort(Expand[T], 1), [T]) + 1),
Transform = Table.TransformRows(
AddCol2,
each List.Zip({{[Name]}, {"Q2-Q1", "Q3-Q2", "Q4-Q3"}, [D], {[Rank]}})
),
Result = Table.FromRows(List.Combine(Transform), {"Name", "QtQ Drop", "Amount", "Rank"})
in
Result
Power Query solution 6 for Rank Sales Drop Per Person, proposed by Abdallah Ally:
let
Source = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content],
AddCol1 = Table.AddColumn(
Source,
"Drop",
each [
a = List.Skip(Record.ToList(_)),
b = List.Skip(a),
c = List.RemoveLastN(a, 1),
d = List.Zip({b, c}),
e = List.Sum(List.Transform(d, each _{0} - _{1}))
][e]
),
AddCol2 = Table.AddColumn(
AddCol1,
"Rank",
each List.PositionOf(List.Sort(AddCol1[Drop], 1), [Drop]) + 1
),
Remove = Table.RemoveColumns(AddCol2, "Drop"),
Transform = Table.TransformRows(
Remove,
each [
a = List.RemoveLastN(List.Skip(Record.ToList(_)), 1),
b = List.Skip(a),
c = List.RemoveLastN(a, 1),
d = List.Zip({b, c}),
e = List.Transform(d, each _{0} - _{1}),
f = List.Zip({{[Name], null, null}, {"Q2-Q1", "Q3-Q2", "Q4-Q3"}, e, {[Rank], null, null}})
][f]
),
Result = Table.FromRows(List.Combine(Transform), {"Name", "QtQ Drop", "Amount", "Rank"})
in
Result
Power Query solution 7 for Rank Sales Drop Per Person, proposed by Eric Laforce:
let
Source = Excel.CurrentWorkbook(){[Name = "tData239"]}[Content],
RankVal = List.Buffer(
List.Sort(List.Distinct(Table.TransformRows(Source, each [Q4] - [Q1])), Order.Descending)
),
TransformRows = List.Accumulate(
Table.ToRows(Source),
{},
(s, r) =>
let
_SplitRow = List.Accumulate(
{1 .. 3},
{},
(s, c) =>
let
_Rec = [
#"QtQ Drop" = "Q" & Text.From(c + 1) & "-Q" & Text.From(c),
Amount = r{c + 1} - r{c}
]
in
s
& {
_Rec
& (
if (c = 1) then
[Name = r{0}, Rank = List.PositionOf(RankVal, r{4} - r{1}) + 1]
else
[]
)
}
)
in
s & _SplitRow
),
Result = Table.FromRecords(
TransformRows,
{"Name", "QtQ Drop", "Amount", "Rank"},
MissingField.UseNull
)
in
Result
Power Query solution 8 for Rank Sales Drop Per Person, proposed by Seokho MOON:
let
Source = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content],
ColNames = {"Name", "QtQ Drop", "Amount", "Rank"},
AddedDrop = Table.AddColumn(Source, "Drop", each [Q4] - [Q1]),
AddedRank = Table.AddColumn(
AddedDrop,
"Rank",
each List.Count(List.Select(AddedDrop[Drop], (x) => [Drop] < x)) + 1
),
Func = (x as list) as list =>
List.Transform(
List.Zip({List.Range(x, 1, 3), List.Range(x, 2, 3)}),
each try _{1} - _{0} otherwise _{1} & "-" & _{0}
),
RowNames = Func(Table.ColumnNames(Source)),
AddedColumn = Table.AddColumn(
AddedRank,
"tbl",
each [
L = Record.ToList(_),
F = Func(L),
R = Table.FromColumns({{[Name]}, RowNames, F, {[Rank]}}, ColNames)
][R]
),
Res = Table.Combine(AddedColumn[tbl])
in
Res
Power Query solution 9 for Rank Sales Drop Per Person, proposed by 🇮🇷 Navid Esmaeilzadeh اسماعیل زاده:
let
S = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content],
A = Table.UnpivotOtherColumns(S, {"Name"}, "QT", "Amount"),
B = Table.Group(
A,
{"Name"},
{{"T", each _, type table [Name = text, QT = text, Amount = number]}}
),
F = (t) =>
let
a = Table.AddIndexColumn(t, "In", 1, 1),
b = Table.AddColumn(a, "QT Drop", each a[QT]{[In]} & "-" & [QT]),
c = Table.AddColumn(b, "TAmount", each b[Amount]{[In]} - [Amount]),
d = Table.RemoveRowsWithErrors(c),
e = Table.AddColumn(d, "Total", each if [In] = 1 then List.Sum(d[TAmount]) else null),
f = Table.SelectColumns(e, {"Name", "QT Drop", "TAmount", "Total"})
in
f,
D = Table.AddColumn(B, "F", each F([T])),
E = Table.Combine(D[F]),
G = Table.SelectRows(E, each ([Total] <> null)),
H = Table.AddRankColumn(G, "Rank", {"Total", 1}, [RankKind = RankKind.Competition]),
I = Table.NestedJoin(E, {"Name", "Total"}, H, {"Name", "Total"}, "R"),
J = Table.SelectColumns(I, {"QT Drop", "TAmount", "Total", "R"}),
K = Table.ExpandTableColumn(J, "R", {"Name", "Rank"}, {"Name", "Rank"}),
L = Table.SelectColumns(K, {"Name", "QT Drop", "TAmount", "Rank"})
in
L
Power Query solution 10 for Rank Sales Drop Per Person, proposed by Peter Krkos:
let
Ad_T = Table.AddColumn(
Source,
"T",
each [
a = List.Skip(Record.FieldNames(_)),
b = List.Transform(
List.Zip({List.Skip(a), List.RemoveLastN(a)}),
(x) => {[Name]}
& {Text.Combine({x{0}, x{1}}, "-"), Record.Field(_, x{0}) - Record.Field(_, x{1})}
),
c = Table.FromRows(b)
][c],
type table
),
Ad_Sum = Table.AddColumn(Ad_T, "Sum", each List.Sum([T][Column3])),
Rank = List.Transform(
Ad_Sum[Sum],
each List.PositionOf(List.Sort(List.Distinct(Ad_Sum[Sum]), 1), _) + 1
),
Transformed = Table.Combine(
List.Transform(
List.Zip(
{List.Transform(Ad_Sum[T], Table.ToColumns), List.Transform(List.Split(Rank, 1), each {_})}
),
(x) => Table.FromColumns(List.Combine(x), {"Name", "QtQ Drop", "Amount", "Rank"})
)
),
ChangedType = Table.TransformColumnTypes(
Transformed,
{{"Name", type text}, {"QtQ Drop", type text}, {"Amount", Int64.Type}, {"Rank", Int64.Type}}
)
in
ChangedType
Power Query solution 11 for Rank Sales Drop Per Person, proposed by Alexandre Garcia:
let
A = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content],
B = List.Transform,
C = (x) =>
let
a = B(
{Table.ColumnNames(A), x},
each
let
x = List.Skip(_)
in
List.RemoveLastN(
B(List.Zip({x, List.Skip(x)}), each try _{1} - _{0} otherwise _{1} & "-" & _{0})
)
)
in
{{x{0}}} & a & {{List.Sum(a{1})}},
D = Table.Combine(
B(Table.ToList(A, C), each Table.FromColumns(_, {"Name", "QtQ Drop", "Amount", "Rank"}))
),
E = Table.TransformColumns(
D,
{
"Rank",
each
let
x = List.PositionOf(List.Sort(List.Distinct(List.RemoveNulls(D[Rank])), 1), _) + 1
in
if x = 0 then null else x
}
)
in
E
Solving the challenge of Rank Sales Drop Per Person with Excel
Excel solution 1 for Rank Sales Drop Per Person, proposed by Bo Rydobon 🇹🇭:
=LET(
x,
B2:E4,
q,
B1:D1,
C,
TOCOL,
d,
DROP(
x,
,
1
)-DROP(
x,
,
-1
),
e,
BYROW(
d,
SUM
),
y,
q="Q1",
HSTACK(
C(
REPT(
A2:A4,
y
)
),
C(
IF(
TAKE(
x,
,
1
)>0,
C1:E1&"-"&q
)
),
C(
d
),
C(
IF(
y,
XMATCH(
e,
-SORT(
-e
)
),
""
)
)
)
)
Excel solution 2 for Rank Sales Drop Per Person, proposed by 🇰🇷 Taeyong Shin:
=LET(n,
B2:E4,
h,
B1:E1,
d,
DROP(
n,
,
1
)-DROP(
n,
,
-1
),
s,
BYROW(
d,
SUM
),
F,
LAMBDA(
x,
TOCOL(
IFNA(
x,
d
)
)
),
q,
F(
DROP(
h,
,
1
)&"-"&DROP(
h,
,
-1
)
),
IF((RIGHT(
q
)="1")+{1,
2,
2,
1}-1,
HSTACK(
F(
A2:A4
),
q,
F(
d
),
F(
XMATCH(
s,
-SORT(
-s
)
)
)
),
""))
Excel solution 3 for Rank Sales Drop Per Person, proposed by Kris Jaganah:
=LET(a,
TOCOL(
A2:A4&"-"&B2:E4&"-"&B1:E1
),
b,
TEXTSPLIT(
a,
"-"
),
c,
--TEXTSPLIT(
TEXTAFTER(
a,
"-"
),
"-"
),
d,
TEXTAFTER(
a,
"-",
2
),
e,
SEQUENCE(
ROWS(
a
)
),
f,
LAMBDA(z,
MAP(e,
b,
LAMBDA(x,
y,
TAKE(FILTER(z,
(e>x)*(b=y),
""),
1)))),
g,
IFERROR(
f(
c
)-c,
),
h,
f(
d
)&"-"&d,
i,
MAP(b,
LAMBDA(z,
-SUM((b=z)*g))),
j,
ROWS(
A2:E4
)-XMATCH(
i,
UNIQUE(
i
)
),
VSTACK(
{"Name",
"QtQ Drop",
"Amount",
"Rank"},
FILTER(
HSTACK(
IF(
d="Q1",
b,
""
),
h,
g,
IF(
d="Q1",
j,
""
)
),
d<>"Q4"
)
))
Excel solution 4 for Rank Sales Drop Per Person, proposed by Julian Poeltl:
=IFNA(
LET(
R,
REDUCE(
HSTACK(
"Name",
"QtQ Drop",
"Amount"
),
SEQUENCE(
ROWS(
A2:A4
)
),
LAMBDA(
A,
B,
VSTACK(
A,
LET(
C,
CHOOSEROWS(
B2:E4,
& B
),
D,
TOCOL(
DROP(
C,
,
1
)-DROP(
C,
,
-1
)
),
HSTACK(
INDEX(
A2:A4,
B
),
TOCOL(
C1:E1&"-"&B1:D1
),
D,
SUM(
D
)
)
)
)
)
),
TR,
TAKE(
R,
,
-1
),
HSTACK(
TAKE(
R,
,
3
),
VSTACK(
"Rank",
DROP(
XMATCH(
TR,
SORT(
TOCOL(
UNIQUE(
TR
),
3
),
,
-1
)
),
1
)
)
)
),
""
)
Excel solution 5 for Rank Sales Drop Per Person, proposed by Oscar Mendez Roca Farell:
=LET(
m,
C2:E4-B2:D4,
b,
BYROW(
m,
SUM
),
O,
TOCOL,
F,
LAMBDA(
i,
O(
REPT(
i,
{1,
0,
0}
)
)
),
HSTACK(
F(
A2:A4
),
O(
IFS(
1^m,
C1:E1&"-"&B1:D1
),
2
),
O(
m
),
IFERROR(
-F(
-XMATCH(
b,
LARGE(
b,
{1,
2,
3}
)
)
),
""
)
)
)
Excel solution 6 for Rank Sales Drop Per Person, proposed by Duy Tùng:
=LET(
f,
LAMBDA(
x,
TOCOL(
IFS(
C2:E4,
x
)
)
),
a,
f(
A2:A4
),
b,
f(
C2:E4-B2:D4
),
c,
GROUPBY(
a,
b,
SUM,
,
0
),
d,
REPT(
a,
XMATCH(
a,
a
)=SEQUENCE(
ROWS(
a
)
)
),
HSTACK(
d,
f(
C1:E1&"-"&B1:D1
),
b,
XLOOKUP(
d,
TAKE(
c,
,
1
),
MAP(
DROP(
c,
,
1
),
LAMBDA(
x,
SUM(
N(
DROP(
c,
,
1
)>x
)
)
)
)+1,
""
)
)
)
Excel solution 7 for Rank Sales Drop Per Person, proposed by Sunny Baggu:
=LET(
_a,
C2:E4 - B2:D4,
_b,
TOCOL(
BYROW(
_a,
LAMBDA(
a,
SUM(
a
)
)
)
),
_s,
SEQUENCE(
ROWS(
_b
)
),
_c,
SORT(
_b,
,
-1
),
_r,
XMATCH(
_b,
_c
),
_n,
TOCOL(
EXPAND(
A2:A4,
,
3,
""
)
),
_q,
TOCOL(
IF(
SEQUENCE(
ROWS(
A2:A4
)
),
C1:E1 & "-" & B1:D1
)
),
_ra,
XLOOKUP(
_n,
A2:A4,
_r,
""
),
HSTACK(
_n,
_q,
TOCOL(
_a
),
_ra
)
)
Excel solution 8 for Rank Sales Drop Per Person, proposed by Md. Zohurul Islam:
=LET(p,
A2:A4,
q,
B1:E1,
r,
B2:E4,
qr,
CHOOSECOLS(
REDUCE(
"",
q,
LAMBDA(
x,
y,
LET(
a,
OFFSET(
y,
0,
1
)&"-"&y,
b,
HSTACK(
x,
a
),
b
)
)
),
2,
3,
4
),
nam,
TOCOL(
IFNA(
p,
qr
)
),
qtr,
TOCOL(
IFNA(
qr,
p
)
),
data,
BYROW(r,
LAMBDA(x,
LET(a,
DROP(
x,
,
1
),
b,
DROP(
x,
,
-1
),
d,
(a-b),
ARRAYTOTEXT(
d
)))),
amt,
DROP(
REDUCE(
"",
data,
LAMBDA(
x,
y,
VSTACK(
x,
TOCOL(
--TEXTSPLIT(
y,
", "
)
)
)
)
),
1
),
rng,
HSTACK(
qtr,
amt
),
u,
MAP(
data,
LAMBDA(
x,
SUM(
--TEXTSPLIT(
x,
", "
)
)
)
),
rnk,
XMATCH(
u,
UNIQUE(
SORT(
u,
,
-1
)
)
),
v,
DROP(
REDUCE(
"",
UNIQUE(
nam
),
LAMBDA(
x,
y,
LET(
e,
FILTER(
rng,
nam=y
),
f,
IFNA(
HSTACK(
y,
e
),
""
),
g,
VSTACK(
x,
f
),
g
)
)
),
1
),
st,
XLOOKUP(
TAKE(
v,
,
1
),
p,
rnk,
""
),
w,
HSTACK(
v,
st
),
hdr,
HSTACK(
"Name",
"QtQ Drop",
"Amount",
"Rank"
),
result,
VSTACK(
hdr,
w
),
result)
Excel solution 9 for Rank Sales Drop Per Person, proposed by Hamidi Hamid:
=LET(
ad,
A2:A4,
x,
TOCOL(
IFNA(
B1:E1,
ad
)
),
s,
VSTACK(
{"",
""}*1,
HSTACK(
DROP(
x,
1
),
DROP(
x,
-1
)
)
),
y,
TOCOL(
-A2:D4+B2:E4
),
g,
TOCOL(
IFNA(
ad,
B1:E1
)
),
u,
TAKE(
s,
,
1
)&"-"&CHOOSECOLS(
s,
2
),
r,
IF(
u="q2-q1",
g,
""
),
m,
HSTACK(
r,
u,
y
),
ff,
FILTER(
m,
NOT(
ISERROR(
TAKE(
m,
,
-1
)
)
)
),
xx,
SORT(
BYROW(
C2:E4-B2:D4,
SUM
),
,
-1
),
mo,
HSTACK(
ad,
SORT(
XMATCH(
xx,
xx
),
,
-1
)
),
ws,
IFERROR(
VLOOKUP(
TAKE(
ff,
,
1
),
mo,
2,
0
),
""
),
VSTACK(
{"Name",
"QtQ Drop",
"Amount",
"Rank"},
HSTACK(
ff,
ws
)
)
)
Excel solution 10 for Rank Sales Drop Per Person, proposed by Asheesh Pahwa:
=LET(
r,
DROP(
REDUCE(
G1:J1,
SEQUENCE(
3
),
LAMBDA(
x,
y,
VSTACK(
x,
LET(
I,
INDEX(
B2:E4,
y,
),
s,
DROP(
SEQUENCE(
COLUMNS(
I
)
)-1,
1
),
d,
DROP(
REDUCE(
"",
s,
LAMBDA(
a,
v,
VSTACK(
a,
LET(
_i,
INDEX(
I,
,
v+1
)-INDEX(
I,
,
v
),
_i2,
INDEX(
B1:E1,
,
v+1
)&"-"&INDEX(
B1:E1,
,
v
),
HSTACK(
_i2,
_i
)
)
)
)
),
1
),
n,
INDEX(
A2:A4,
y,
),
IFNA(
HSTACK(
n,
d,
SUM(
d
)
),
""
)
)
)
)
),
1
),
t,
TAKE(
r,
,
-1
),
u,
SORT(
UNIQUE(
FILTER(
t,
t<>""
)
),
,
-1
),
HSTACK(
DROP(
r,
,
-1
),
XLOOKUP(
t,
u,
SEQUENCE(
ROWS(
u
)
),
""
)
)
)
Excel solution 11 for Rank Sales Drop Per Person, proposed by ferhat CK:
=LET(
a,
A2:E4,
b,
C2:E4-B2:D4,
IFNA(
REDUCE(
G1:J1,
SEQUENCE(
ROWS(
a
)
),
LAMBDA(
x,
y,
VSTACK(
x,
HSTACK(
CHOOSEROWS(
TAKE(
a,
,
1
),
y
),
TOCOL(
C1:E1&"-"&B1:D1
),
TOCOL(
CHOOSEROWS(
b,
y
)
),
XMATCH(
SUM(
CHOOSEROWS(
b,
y
)
),
SORT(
BYROW(
b,
SUM
),
,
-1
)
)
)
)
)
),
""
)
)
Excel solution 12 for Rank Sales Drop Per Person, proposed by Eddy Wijaya:
=LET(
r_gl,
SORT(
BYROW(
B2:E4,
LAMBDA(
r,
SUM(
DROP(
r-OFFSET(
r,
,
-1
),
,
1
)
)
)
),
,
-1
),
r,
REDUCE(
G1:J1,
A2:A4,
LAMBDA(
a,
v,
VSTACK(
a,
IFNA(
HSTACK(
v,
TOCOL(
C1:E1&"-"&B1:D1
),
LET(
am,
TOCOL(
OFFSET(
v,
,
2,
1,
3
)-OFFSET(
v,
,
1,
1,
3
)
),
HSTACK(
am,
XMATCH(
SUM(
am
),
r_gl,
0
)
)
)
),
""
)
)
)
),
r
)
Excel solution 13 for Rank Sales Drop Per Person, proposed by Miguel Angel Franco García:
=LET(
a;
A2:A4&"-"&B1:D1&" "&C1:E1;
b;
ENCOL(
a
);
c;
C2:E4-B2:D4;
d;
ENCOL(
c
);
e;
ENCOL(
A2:C4
);
f;
SI(
ESNUMERO(
e
);
"";
e
);
APILARH(
f;
TEXTODESPUES(
b;
"-"
);
d
)
)
Solving the challenge of Rank Sales Drop Per Person with Python
Python solution 1 for Rank Sales Drop Per Person, proposed by Konrad Gryczan, PhD:
import pandas as pd
path = "PQ_Challenge_239.xlsx"
input = pd.read_excel(path, usecols="A:E", nrows=3)
test = pd.read_excel(path, useco&ls="G:J", nrows=9).rename(columns=lambda x: x.split('.')[0])
input['rownumber'] = input.reset_index().index + 1
input_long = input.melt(id_vars=['Name', 'rownumber'], var_name='quarter', value_name='sales')
input_long['QtQ Drop'] = input_long.groupby('Name')['quarter'].shift(-1) + "-" + input_long['quarter']
input_long['Amount'] = input_long.groupby('Name')['sales'].shift(-1) - input_long['sales']
input_long['Rank'] = input_long.groupby('Name')['Amount'].transform('sum').rank(method='dense', ascending=False)
input_long = input_long.sort_values(by=['rownumber', 'quarter', "Rank"])
input_long.loc[input_long['quarter'] != 'Q1', ['Name', 'Rank']] = None
result = input_long.dropna(subset=['Amount']).loc[:, ['Name', 'QtQ Drop', 'Amount', 'Rank']].reset_index(drop=True)
result['Amount'] = result['Amount'].astype('int64')
print(result.equals(test)) # True
Solving the challenge of Rank Sales Drop Per Person with Python in Excel
Python in Excel solution 1 for Rank Sales Drop Per Person, proposed by Alejandro Campos:
df = xl("A1:E4", headers=True)
# Calculate quarter-to-quarter drops
for i in range(1, 4):
df[f'Q{i+1}-Q{i}'] = df[f'Q{i+1}'] - df[f'Q{i}']
# Create result DataFrame
result = pd.concat([
pd.DataFrame({
'Name': [row['Name']] + [''] * 2,
'QtQ Drop': [f'Q{i+1}-Q{i}' for i in range(1, 4)],
'Amount': [row[f'Q{i+1}-Q{i}'] for i in range(1, 4)],
'Rank': None
}) for _, row in df.iterrows()
], ignore_index=True)
# Calculate and assign ranks
total_drop = df.assign(TotalDrop=df[['Q2-Q1', 'Q3-Q2', 'Q4-Q3']].sum(axis=1))
total_drop['Rank'] = total_drop['TotalDrop'].rank(ascending=False).astype(int)
result['Rank'] = result['Name'].map(dict(zip(total_drop['Name'],
total_drop['Rank']))).fillna(' ')
result
Solving the challenge of Rank Sales Drop Per Person with R
R solution 1 for Rank Sales Drop Per Person, proposed by Konrad Gryczan, PhD:
library(tidyverse)
library(readxl)
path = "Power Query/PQ_Challenge_239.xlsx"
input = read_excel(path, range = "A1:E4")
test = read_excel(path, range = "G1:J10")
result = input %>%
pivot_longer(cols = -c(1), names_to = "quarter", values_to = "sales") %>%
mutate(`QtQ Drop` = paste0(lead(quarter),"-",quarter),
Amount = lead(sales) - sales,
tot_amount = sum(Amount, na.rm = TRUE),
.by = Name) %>%
mutate(Rank = dense_rank(-tot_amount),
Name = ifelse(quarter == "Q1", Name, NA),
Rank = ifelse(quarter == "Q1", Rank, NA)) %>%
filter(!is.na(Amount)) %>%
select(Name, `QtQ Drop`, Amount, Rank)
all.equal(result, test, check.attributes = FALSE)
#> [1] TRUE
&
