חשיבות ניהול אנשי המכירות בחברה ידועה. והמשימה הופכת קלה יותר כשיש כלים כמו SQL ו – PBI. את המודל הבא בניתי תחילה בSQL, ואז עברתי ל PBI כדי לבנות את הדהשבורד.

ישנם המון פלטפורמות לצורך כתיבת שאילתות SQL. ניתן להשתמש ב MYSQL, ולבנות מסד נתונים שלם ומקצועי. לשם הפשטות ולצורך המודל הזה השתמשתי בפלטפורמה חינמית ומעולה – data.world.

הפלטפורמה הזו מאפשרת כתיבת שאילתות SQL ברמות שונות, ולמרות שאין בה את כל הביטויים (פונקציות) הסטנדרטיים, ניתן בהחלט להשתמש בה לכתיבת שאילתות מקצועיות. בנוסף ניתן לבצע אינטגרציה מעולה עם PBI, בהמשך אראה איך עושים את זה.

הדהשבורד הסופי (ניתן ללחוץ על התמונה להגדלה):

שאילתות SQL

פלטפורמת דאטה-וורלד מאפשרת לאנליסטים שלוש פעולות ETL רלוונטיות לנו:

1> העלאת מסד נתונים בקבצי CSV שעליהן ניתן לכתוב את השאילתות.

2> כתיבת שאילתות SQL ושמירתן כמסד נתונים נפרד (הפלטפורמה אינה מאפשרת יצירת טבלה – create table, אבל השאילתות מתפקדות כמסד נתונים עצמאי שניתן לשאוב לפלטפומות אחרות).

3> אינטגרציה ישירה עם פלטפורמות אחרות כגון PBI, Tableau  ועוד.

כמה טיפים חשובים ינתנו בהמשך.

הטבלאות עליהן נבצע ETL הן:

טבלת Sales – טבלת רישומי פעילות מכירה, הכוללת תאריך הפעולה, פרטים על המוצר, נתוני מכירה מספריים (כמות, מחיר ללקוח), נתונים על ססטוס הפעולה ( נשלח ללקוח, בוטל, בתהליך וכו’), נתונים על הלקוח כולל איזור מכירה, קוד איש המכירות האחראי ועוד.

ניתן ללחוץ על התמונה להגדלה

טבלת אנשי מכירות – טבלה שבניתי, המתרגמת את קוד איש המכירות (מפתח ראשי) לשם שלו.

כך נראה מסד הנתונים שהקמנו בדאטה-וורלד (ניתן ללחוץ על התמונה להגדלה)

שאילתה ראשונה – Sales Table

השאילתה הזו מבצעת את הפעולות הבאות:

1> מציגה רק את העמודות מתוך טבלת Sales, הדרושות למודל.

2> בונה את עמודת SalePrice שהיא מכפלה של הכמות הנמכרת במחיר המוצר (ההכפלה ב 10 נדרשה כדי להביא את המספר לסכומים נוחים לעבודה).

3> בונה את עמודת profit באופן דומה לעמודה הקודמת שבנינו.

4> מבצעת חיבור JOIN של עמודת “שם איש המכירות” מטבלת salesman לטבלת Sales על בסיס עמודות קוד איש המכירות salesman_key.

SELECT
    UPPER(salesman.salesman_name) AS salesman_name, 
    CAST(salestable.orderdate AS DATE) AS TDATE,
    salestable.quantityordered, salestable.priceeach, salestable.quantityordered * salestable.priceeach * 10 AS SalePrice,
    CAST((salestable.quantityordered * salestable.priceeach) AS INTEGER) AS profit,
    salestable.status,  salestable.productline ,salestable.productcode,salestable.customername, salestable.dealsize
FROM salestable
JOIN salesman on salestable.salesman_key = salesman.salesman_key
ORDER BY TDATE
;

שאילתה שניה – Customer First Record

השאילתה הזו הייתה דרושה לצורך חישוב כמות הלקוחות החדשים בכל תקופה. באמצעות שימוש בפקודה FIRST_VALUE, קיבלנו את התאריך בו הלקוח נכנס לראשונה לרישומים שלנו בטבלת sales.

 

SELECT DISTINCT 
salestable.customername, 
FIRST_VALUE(CAST(salestable.orderdate AS DATE)) OVER (PARTITION BY salestable.customername ORDER BY salestable.orderdate) AS firstday
FROM salestable
ORDER BY salestable.orderdate
;

שאילתה שלישית – Territory

השאילתה מפרידה את הנתונים הגאוגרפיים של הלקוחות לטבלה חדשה, לצורך נוחות בעבודה אח”כ.

SELECT 
     sales.customername, sales.city, sales.state, sales.territory, sales.country
FROM sales
GROUP BY sales.customername
;

שאיבת מסד הנתונים ל PBI

ניתן לבצע אינטגרציה ישירות בעזרת כפתור Open With PowerBi הנמצא בכל שאילתת SQL, אבל מנסיון האינטגרציה באופן הזה פחות מדוייקת.

הדרך היותר יעילה לעשות זאת היא כך:

לכל שאילתה יש כפתור DOWNLOAD. לחיצה עליו מציגה מספר אפשרויות. יש ללחוץ על האפשרות  Copy  URLOr Embed code:

 

 

קופץ החלון הבא שבו יש לבצע שתי פעולות:

1> להפעיל את האפשרות “Allow changes to the original query to update”. זה יאפשר לשינויים שנעשה בשאילתה לאחר מכן, להתעדכן ב PBI.

2> להעתיק את הלינק (הכתובת הראשונה), וללחוץ DONE.

 

את הכתובת שהעתקנו יש להדביק ב PBI כמקור נתונים אינטרנטי: GET DATA => WEB, ולטעון.

את הפעולה יש לבצע לכל אחת משלושת השאילות שכתבנו עד כה.

מכאן והלאה מקבלים טבלת נתונים לכל דבר ב PBI.

בניית המודל ב PBI

כך נראה המודל במבט מלמעלה. שימו לב שהוספתי טבלת DATE שאני בונה בכל מודל שלי, וטבלת SelectPeriod הנדרשת לצורך חיתוך תקופתי. הרחבתי על השיטה הזו בפוסט הזה , אם לא קראתם, כדאי לקרוא אותו לפני שממשיכים.

 

והנה גם מיפוי הקשרים בין עמודות הטבלאות:

נבנה את הנוסחאות למודל:

השוואת מחזורי מכירה בין אנשי המכירות

נוסחה 1 – סכום המכירות מטבלת SALES TABLE:

sales = SUM('SALES TABLE'[SalePrice])

 

נוסחה 2 – סכום המכירות בחיתוך תקופתי קבוע מראש: חודש, רבעון ושנה. את ההגיון מאחורי השיטה, כאמור, הסברתי במאמר קודם

Sales Bookings = 

var selectedperiod = SELECTEDVALUE(SelectPeriod[Select Period])
var salesCM = CALCULATE([sales],'Date'[Current Month] = "True")
var salesCQ = CALCULATE([sales],'Date'[Current Qurter] = "True")
var salesCY = CALCULATE([sales],'Date'[Current Year] = "True")

Return 

switch
    (
    true(),
    selectedperiod="Current Month", salesCM,
    selectedperiod="Quarter To Date", salesCQ,
    selectedperiod="Year to Date", salesCY
    )

 

נוסחה 3 – סכום המכירות אשתקד, בחיתוך תקופתי. הנוסחה לוקחת את הנוסחה הקודמת ומשתמשת בפקודות דאקס DATESYTD, על מנת לקבל את הנתונים המקבילים בשנה הקודמת:

Sales Bookings YTD = 
var selectedperiod = SELECTEDVALUE(SelectPeriod[Select Period])
var salesCM = CALCULATE([sales],DATESMTD(dateadd('Date'[Date],-1,Year))) 
var salesCQ = CALCULATE([sales],DATESQTD(dateadd('Date'[Date],-1,Year))) 
var salesCY = CALCULATE([sales],DATESYTD(dateadd('Date'[Date],-1,Year))) 

Return 

switch
    (
    true(),
    selectedperiod="Current Month", salesCM,
    selectedperiod="Quarter To Date", salesCQ,
    selectedperiod="Year to Date", salesCY
    )

שיעור סגירת עסקאות

כדי לחשב את שיעור סגירת עסקאות יש לחשב את מספר העסקאות הסגורות ואת מספר העסקאות הכולל את הפתוחות (או הלא סגורות):

מספר העסקאות הסגורות – הנחתי שעסקה סגורה מופיעה בסטטוס “Shipped”:

Close transactions number = 

var selectedperiod = SELECTEDVALUE(SelectPeriod[Select Period])
var Shipped = FILTER('SALES TABLE', 'SALES TABLE'[status] = "Shipped")
var CMF = FILTER('Date', 'Date'[Current Month] = "True") 
var CqF = FILTER('Date', 'Date'[Current Qurter] = "True")
var CyF = FILTER('Date', 'Date'[Current Year] = "True")


var CM = CALCULATE(COUNTROWS('SALES TABLE'),CMF,Shipped)
var CQ = CALCULATE(COUNTROWS('SALES TABLE'),CqF,Shipped)
var CY = CALCULATE(COUNTROWS('SALES TABLE'),CyF,Shipped)

Return 

switch
    (
    true(),
    selectedperiod="Current Month", CM,
    selectedperiod="Quarter To Date", CQ,
    selectedperiod="Year to Date", CY
    )

 

מספר העסקאות כולל הפתוחות:

Close Leads number = 

var selectedperiod = SELECTEDVALUE(SelectPeriod[Select Period])
var CMF = FILTER('Date', 'Date'[Current Month] = "True") 
var CqF = FILTER('Date', 'Date'[Current Qurter] = "True")
var CyF = FILTER('Date', 'Date'[Current Year] = "True")


var CM = CALCULATE(COUNTROWS('SALES TABLE'),CMF)
var CQ = CALCULATE(COUNTROWS('SALES TABLE'),CqF)
var CY = CALCULATE(COUNTROWS('SALES TABLE'),CyF)

Return 

switch
    (
    true(),
    selectedperiod="Current Month", CM,
    selectedperiod="Quarter To Date", CQ,
    selectedperiod="Year to Date", CY
    )

 

ועכשיו ניתן לחשב את שיעור העסקאות הסגורות מתוך כל הלידים לתקופה:

 

Lead to Win Rate = 
[Close transactions number]/[Close Leads number]

עלות רכישת לקוח ועלות רכישת ליד

כדי לחשב עלות פר לקוח סגור או פר ליד, יש לחשב את מספר הלקוחות/לידים חדשים בכל תקופה. שימו לב שכאן נכנסת לפעולה טבלת CUSTOMER FIRST RECORD אותה בנינו כשאילתת SQL בהתחלת הפוסט.

מספר הלקוחות החדשים לתקופה:

new customrs number = 

var selectedperiod = SELECTEDVALUE(SelectPeriod[Select Period])
var Shipped = FILTER('SALES TABLE', 'SALES TABLE'[status] = "Shipped")
var CMF = FILTER('Date', 'Date'[Current Month] = "True") 
var CqF = FILTER('Date', 'Date'[Current Qurter] = "True")
var CyF = FILTER('Date', 'Date'[Current Year] = "True")


var CM = CALCULATE(COUNTROWS('CUSTOMER  FIRST RECORD'),CMF,Shipped)
var CQ = CALCULATE(COUNTROWS('CUSTOMER  FIRST RECORD'),CqF,Shipped)
var CY = CALCULATE(COUNTROWS('CUSTOMER  FIRST RECORD'),CyF,Shipped)

Return 

switch
    (
    true(),
    selectedperiod="Current Month", CM,
    selectedperiod="Quarter To Date", CQ,
    selectedperiod="Year to Date", CY
    )

 

מספר הלידים החדשים לתקופה:

new lead number = 

var selectedperiod = SELECTEDVALUE(SelectPeriod[Select Period])

var CMF = FILTER('Date', 'Date'[Current Month] = "True") 
var CqF = FILTER('Date', 'Date'[Current Qurter] = "True")
var CyF = FILTER('Date', 'Date'[Current Year] = "True")


var CM = CALCULATE(COUNTROWS('CUSTOMER  FIRST RECORD'),CMF)
var CQ = CALCULATE(COUNTROWS('CUSTOMER  FIRST RECORD'),CqF)
var CY = CALCULATE(COUNTROWS('CUSTOMER  FIRST RECORD'),CyF)

Return 

switch
    (
    true(),
    selectedperiod="Current Month", CM,
    selectedperiod="Quarter To Date", CQ,
    selectedperiod="Year to Date", CY
    )

 

עלות פר-ליד:

Cost per Lead = 
var selectedperiod = SELECTEDVALUE(SelectPeriod[Select Period])
var CM = (2000000/12)/[new lead number]
var CQ = 500000/[new lead number]
var CY = 2000000/[new lead number]

Return 

switch
    (
    true(),
    selectedperiod="Current Month", CM,
    selectedperiod="Quarter To Date", CQ,
    selectedperiod="Year to Date", CY
    )

 

עלות רכישת לקוח Customer Acquisition Cost (CAC):

 

CAC = 
var selectedperiod = SELECTEDVALUE(SelectPeriod[Select Period])
var cost = 2000000
var CM = (cost/12)/[new customrs number]
var CQ = (cost/4)/[new customrs number]
var CY = cost/[new customrs number]

Return 

switch
    (
    true(),
    selectedperiod="Current Month", CM,
    selectedperiod="Quarter To Date",CQ,
    selectedperiod="Year to Date", CY
    )

שיעור רווח פר-לקוח – תרשים פיזור

כדי לבנות את תרשים הפיזור המציג את שיעור הרווח פר לקוח יש לבנות נוסחה פשוטה של שיעור רווח מתוך המכירות בחיתוך לפי תקופה:

Profit Ratio = 

var PRatio = sumx('SALES TABLE', 'SALES TABLE'[profit]/ 'SALES TABLE'[SalePrice])
var selectedperiod = SELECTEDVALUE(SelectPeriod[Select Period])
var salesCM = CALCULATE(PRatio,'Date'[Current Month] = "True")
var salesCQ = CALCULATE(PRatio,'Date'[Current Qurter] = "True")
var salesCY = CALCULATE(PRatio,'Date'[Current Year] = "True")

Return 

switch
    (
    true(),
    selectedperiod="Current Month", salesCM,
    selectedperiod="Quarter To Date", salesCQ,
    selectedperiod="Year to Date", salesCY
    )

קבצים מצורפים:

https://bit.ly/3H0EuVc