ื•ื•ื™ ืฆื• ื–ืึทืžืœืขืŸ ื‘ืึทื ื™ืฆืขืจ ืงืึธื”ืึธืจืฅ ื•ื•ื™ ื’ืจืึทืคืก ืื™ืŸ ื’ืจืึทืคืึทื ืึท [+ ื“ืึธืงืงืขืจ ื‘ื™ืœื“ ืžื™ื˜ ื‘ื™ื™ึทืฉืคึผื™ืœ]

ื•ื•ื™ ืฆื• ื–ืึทืžืœืขืŸ ื‘ืึทื ื™ืฆืขืจ ืงืึธื”ืึธืจืฅ ื•ื•ื™ ื’ืจืึทืคืก ืื™ืŸ ื’ืจืึทืคืึทื ืึท [+ ื“ืึธืงืงืขืจ ื‘ื™ืœื“ ืžื™ื˜ ื‘ื™ื™ึทืฉืคึผื™ืœ]

ื•ื•ื™ ืžื™ืจ ืกืึทืœื•ื•ื“ ื“ื™ ืคึผืจืึธื‘ืœืขื ืคื•ืŸ ื•ื•ื™ื–ืฉื•ื•ืึทืœื™ื™ื–ื™ื ื’ ื‘ืึทื ื™ืฆืขืจ ืงืึธื”ืึธืจืฅ ืื™ืŸ ื“ื™ ืคึผืจืึธืžืึธืคึผื•ืœื˜ ื“ื™ื ืกื˜ ื ื™ืฆืŸ Grafana.

ื”ืขื›ืขืจืŸ - ืึท ืฉื˜ืึทืจืง ื“ื™ื ืกื˜ ืžื™ื˜ ืึท ื’ืจื•ื™ืก ื ื•ืžืขืจ ืคื•ืŸ ื ื™ืฆืขืจืก. ืื™ื‘ืขืจ ื“ื™ 10 ื™ืึธืจ ืคื•ืŸ ืึธืคึผืขืจืึทืฆื™ืข, ื“ื™ ื ื•ืžืขืจ ืคื•ืŸ ืจืขื“ื–ืฉื™ืกื˜ืจื™ื™ืฉืึทื ื– ืื™ืŸ ื“ื™ ืกื™ืกื˜ืขื ืื™ื– ื™ืงืกื™ื“ื™ื“ ืึท ืžื™ืœื™ืึธืŸ. ื™ืขื ืข ื•ื•ืืก ื”ืึธื‘ืŸ ื’ืขืคึผืœืึธื ื˜ืขืจื˜ ืขื ืœืขืš ื‘ืึทื“ื™ื ื•ื ื’ืก ื•ื•ื™ืกืŸ ืึทื– ื“ื™ ืžืขื ื’ืข ืคื•ืŸ โ€‹โ€‹ื ื™ืฆืขืจืก ืื™ื– ื•ื•ื™ื™ึทื˜ ืคื•ืŸ ื›ืึธื•ืžืึทื“ื–ืฉื™ื ื™ืึทืก.

ืขืžืขืฅ ื”ืื˜ ื–ื™ืš ืื™ื™ื ื’ืขืฉืจื™ื‘ืŸ ืื•ืŸ "ืื™ื™ื‘ื™ื’ ืื™ื™ื ื’ืขืฉืœืืคืŸ". ืขืžืขืฆืขืจ ืคืืจื’ืขืกืŸ ื–ื™ื™ืขืจ ืคึผืึทืจืึธืœ ืื•ืŸ ืจืขื’ื™ืกื˜ืจื™ืจื˜ ืึท ืคึผืึธืจ ืžืขืจ ืžืึธืœ ืื™ืŸ ื“ื™ ืœื•ื™ืฃ ืคื•ืŸ ื–ืขืงืก ื—ื“ืฉื™ื. ืขืžืขืฆืขืจ ื‘ืจืขื ื’ื˜ ื’ืขืœื˜ ืฆื• ื“ื™ ืงืึทืฉ ืจืขื’ื™ืกื˜ืจื™ืจืŸ, ืื•ืŸ ืขืžืขืฆืขืจ ื’ืขืงื•ืžืขืŸ ืคึฟืึทืจ ืคืจื™ื™ ืื™ื ืกื˜ืจื•ืžืขื ื˜ืŸ. ืื•ืŸ ืขืก ื•ื•ืึธืœื˜ ื–ื™ื™ืŸ ืคื™ื™ึทืŸ ืฆื• ื‘ืึทืงื•ืžืขืŸ ืขื˜ืœืขื›ืข ื ื•ืฅ ืคื•ืŸ ืึทืœืขืžืขืŸ.

ืื•ื™ืฃ ืึทื–ืึท ื’ืจื•ื™ืก ื“ืึทื˜ืŸ ืฉื˜ืขืœื˜ ื•ื•ื™ ืื•ื ื“ื–ืขืจ, ืึทื ืึทืœื™ื™ื–ื™ื ื’ ื“ื™ ื ืึทื˜ื•ืจ ืคื•ืŸ ืึท ื™ื—ื™ื“ ื‘ืึทื ื™ืฆืขืจ ืื•ืŸ ืžืึทื›ืŸ ืžื™ืงืจืึธ-ื“ื™ืกื™ื–ืฉืึทื ื– ืื™ื– ื•ืžื–ื™ืกื˜. ืื‘ืขืจ ืงืึทื˜ืฉื™ื ื’ ื˜ืจืขื ื“ืก ืื•ืŸ ืืจื‘ืขื˜ืŸ ืžื™ื˜ ื’ืจื•ื™ืก ื’ืจื•ืคึผืขืก ืื™ื– ืžืขื’ืœืขืš ืื•ืŸ ื ื™ื™ื˜ื™ืง. ื•ื•ืึธืก ืื™ื– ืคึผื•ื ืงื˜ ื•ื•ืึธืก ืžื™ืจ ื˜ืึธืŸ.

Summary

  1. ื•ื•ืึธืก ืื™ื– ืงืึธื”ืึธืจื˜ ืึทื ืึทืœื™ืกื™ืก ืื•ืŸ ื•ื•ืึธืก ืื™ื– ืขืก ื“ืืจืฃ?
  2. ื•ื•ื™ ืฆื• ืžืึทื›ืŸ ืงืึธื”ืึธืจืฅ ืœื•ื™ื˜ ื—ื•ื“ืฉ ืคื•ืŸ ื‘ืึทื ื™ืฆืขืจ ืจืขื’ื™ืกื˜ืจืึทืฆื™ืข ืื™ืŸ SQL.
  3. ื•ื•ื™ ืฆื• ืึทืจื™ื‘ืขืจืคื™ืจืŸ ืงืึธื”ืึธืจืฅ ืฆื• ื’ืจืืคืื ื.

ืื•ื™ื‘ ืื™ืจ ืฉื•ื™ืŸ ื•ื•ื™ืกืŸ ื•ื•ืึธืก ืงืึธื”ืึธืจื˜ ืึทื ืึทืœื™ืกื™ืก ืื™ื– ืื•ืŸ ื•ื•ื™ ืฆื• ื˜ืึธืŸ ื“ืึธืก ืื™ืŸ SQL, ื”ืึธืคึผืงืขืŸ ื’ืœื™ื™ืš ืฆื• ื“ื™ ืœืขืฆื˜ืข ืึธืคึผื˜ื™ื™ืœื•ื ื’.

1. ื•ื•ืึธืก ืื™ื– ืงืึธื”ืึธืจื˜ ืึทื ืึทืœื™ืกื™ืก ืื•ืŸ ื•ื•ืึธืก ืื™ื– ืขืก ื“ืืจืฃ?

ืงืึธื”ืึธืจื˜ ืึทื ืึทืœื™ืกื™ืก ืื™ื– ืึท ืžืขื˜ืึธื“ ื‘ืื–ื™ืจื˜ ืื•ื™ืฃ ืงืึทืžืคึผืขืจื™ื ื’ ืคืึทืจืฉื™ื“ืขื ืข ื’ืจื•ืคึผืขืก (ืงืึธื”ืึธืจืฅ) ืคื•ืŸ ื ื™ืฆืขืจืก. ืจื•ื‘ึฟ ืึธืคื˜, ืื•ื ื“ื–ืขืจ ื’ืจื•ืคึผืขืก ื–ืขื ืขืŸ ื’ืขืฉืืคืŸ ื“ื•ืจืš ื“ื™ ื•ื•ืึธืš ืึธื“ืขืจ ื—ื•ื“ืฉ ืื™ืŸ ื•ื•ืึธืก ื“ืขืจ ื‘ืึทื ื™ืฆืขืจ ืื ื’ืขื”ื•ื™ื‘ืŸ ื ื™ืฆืŸ ื“ื™ ืกืขืจื•ื•ื™ืก. ืคื•ืŸ ื“ืึธ ื“ื™ ื‘ืึทื ื™ืฆืขืจ 'ืก ืœืขื‘ืŸ ืื™ื– ืงืึทืœืงื™ืึทืœื™ื™ื˜ื™ื“, ืื•ืŸ ื“ืึธืก ืื™ื– ืึท ื’ืจืื“ืŸ ืื•ื™ืฃ ื“ืขืจ ื‘ืื–ืข ืคื•ืŸ โ€‹โ€‹ื•ื•ืึธืก ืงืขื ืขืŸ ื–ื™ื™ืŸ ื“ื•ืจื›ื’ืขืงืึธื›ื˜ ื’ืึทื ืฅ ืงืึธืžืคึผืœื™ืฆื™ืจื˜ ืึทื ืึทืœื™ืกื™ืก. ืคึฟืึทืจ ื‘ื™ื™ึทืฉืคึผื™ืœ, ืคึฟืึทืจืฉื˜ื™ื™ืŸ:

  • ื•ื•ื™ ื˜ื•ื˜ ื“ืขืจ ืึทืงื•ื•ืึทื–ื™ืฉืึทืŸ ืงืึทื ืึทืœ ื”ืฉืคึผืขื” ื“ื™ ืœืขื‘ืŸ ืคื•ืŸ ื“ื™ ื‘ืึทื ื™ืฆืขืจ;
  • ื•ื•ื™ ื“ื™ ื ื•ืฆืŸ ืคื•ืŸ ืงื™ื™ืŸ ืฉื˜ืจื™ืš ืึธื“ืขืจ ื“ื™ื ืกื˜ ืึทืคืขืงืฅ ืœืขื‘ืŸ;
  • ื•ื•ื™ ื“ื™ ืงืึทื˜ืขืจ ืคื•ืŸ ืฉื˜ืจื™ืš X ืึทืคืขืงื˜ืึทื“ ื“ื™ ืœืขื‘ืŸ ืงืึทืžืคึผืขืจื“ ืžื™ื˜ ืœืขืฆื˜ืข ื™ืึธืจ.

2. ื•ื•ื™ ืฆื• ืžืึทื›ืŸ ืงืึธื”ืึธืจืฅ ืื™ืŸ ืกืงืœ?

ื“ื™ ื’ืจื™ื™ืก ืคื•ืŸ ื“ืขื ืึทืจื˜ื™ืงืœ ืื•ืŸ ืกื™ื™ื›ืœ ื˜ืึธืŸ ื ื™ื˜ ืœืึธื–ืŸ ืื•ื ื“ื– ืฆื• ืคืึธืจืฉื˜ืขืœืŸ ืื•ื ื“ื–ืขืจ ืคืึทืงื˜ื™ืฉ ื“ืึทื˜ืŸ ื“ืึธ - ืื™ืŸ ื“ื™ ืคึผืจืึธื‘ืข ื“ืึทืžืคึผ, ืกื˜ืึทื˜ื™ืกื˜ื™ืง ืคึฟืึทืจ ืึท ื™ืึธืจ ืื•ืŸ ืึท ื”ืึทืœื‘: 1200 ื ื™ืฆืขืจืก ืื•ืŸ 53 ื˜ืจืึทื ื–ืึทืงืฉืึทื ื–. ืึทื–ื•ื™ ืึทื– ืื™ืจ ืงืขื ืขืŸ ืฉืคึผื™ืœืŸ ืžื™ื˜ ื“ื™ ื“ืึทื˜ืŸ, ืžื™ืจ ื”ืึธื‘ืŸ ืฆื•ื’ืขื’ืจื™ื™ื˜ ืึท ื“ืึธืงืงืขืจ ื‘ื™ืœื“ ืžื™ื˜ MySQL ืื•ืŸ Grafana ืื™ืŸ ื•ื•ืึธืก ืื™ืจ ืงืขื ืขืŸ ื“ืขืจืคืึทืจื•ื ื’ ืขืก ืึทืœืข ื–ื™ืš. ืœื™ื ืง ืฆื• GitHub ืื™ืŸ ื“ื™ ืกื•ืฃ ืคื•ืŸ ื“ืขื ืึทืจื˜ื™ืงืœ.

ืื•ืŸ ื“ืึธ ืžื™ืจ ื•ื•ืขืœืŸ ื•ื•ื™ื™ึทื–ืŸ ื“ื™ ืฉืึทืคื•ื ื’ ืคื•ืŸ ืงืึธื”ืึธืจืฅ ื ื™ืฆืŸ ืึท ืกื™ืžืคึผืœืึทืคื™ื™ื“ ื‘ื™ื™ึทืฉืคึผื™ืœ.

ื–ืืœ ืก ื™ื‘ืขืจื ืขืžืขืŸ ืžื™ืจ ื”ืึธื‘ืŸ ืึท ื“ื™ื ืกื˜. ื™ื•ื–ืขืจื– ืคืึทืจืฉืจื™ื™ึทื‘ืŸ ื“ืึธืจื˜ ืื•ืŸ ืคืึทืจื‘ืจืขื ื’ืขืŸ ื’ืขืœื˜ ืื•ื™ืฃ ืกืขืจื•ื•ื™ืกืขืก. ืื™ื‘ืขืจ ืฆื™ื™ึทื˜, ื ื™ืฆืขืจืก ืคืึทืœืŸ ืื•ื™ืก. ืžื™ืจ ื•ื•ื™ืœืŸ ืฆื• ื’ืขืคึฟื™ื ืขืŸ ืื•ื™ืก ื•ื•ื™ ืœืึทื ื’ ื™ื•ื–ืขืจื– ืœืขื‘ืŸ, ืื•ืŸ ื•ื•ื™ ืคื™ืœืข ืคื•ืŸ โ€‹โ€‹ื–ื™ื™ ืคืึทืœืŸ ืึทื•ื•ืขืง ื ืึธืš ื“ื™ 1 ืื•ืŸ 2 ื—ื•ื“ืฉ ืคื•ืŸ ื ื™ืฆืŸ ื“ื™ ื“ื™ื ืกื˜.

ืฆื• ืขื ื˜ืคึฟืขืจืŸ ื“ื™ ืคึฟืจืื’ืŸ, ืžื™ืจ ื“ืึทืจืคึฟืŸ ืฆื• ื‘ื•ื™ืขืŸ ืงืึธื”ืึธืจืฅ ื‘ืื–ื™ืจื˜ ืื•ื™ืฃ ื“ื™ ื—ื•ื“ืฉ ืคื•ืŸ ืจืขื’ื™ืกื˜ืจืึทืฆื™ืข. ืžื™ืจ ื•ื•ืขืœืŸ ืžืขืกื˜ืŸ ืึทืงื˜ื™ื•ื•ื™ื˜ืขื˜ ืœื•ื™ื˜ ื”ื•ืฆืื•ืช ืื™ืŸ ื™ืขื“ืขืจ ื—ื•ื“ืฉ. ืึทื ืฉื˜ืึธื˜ ื”ื•ืฆืื•ืช, ืขืก ืงืขืŸ ื–ื™ื™ืŸ ืึธืจื“ืขืจืก, ืึทื‘ืึธื ืขืžืขื ื˜ ืคื™ื– ืึธื“ืขืจ ืงื™ื™ืŸ ืื ื“ืขืจืข ืฆื™ื™ื˜-ื‘ืื–ื™ืจื˜ ื˜ืขื˜ื™ืงื™ื™ื˜.

ืขืจืฉื˜ ื“ืึทื˜ืข

ื“ื™ ื‘ื™ื™ืฉืคื™ืœืŸ ื–ืขื ืขืŸ ื’ืขืžืื›ื˜ ืื™ืŸ MySQL, ืึธื‘ืขืจ ืคึฟืึทืจ ืื ื“ืขืจืข DBMS ืขืก ื–ืึธืœ ื ื™ืฉื˜ ื–ื™ื™ืŸ ืงื™ื™ืŸ ื‘ืึทื˜ื™ื™ึทื˜ื™ืง ื“ื™ืคืขืจืึทื ืกื™ื–.

ื‘ืึทื ื™ืฆืขืจ ื˜ื™ืฉ - ื•ืกืขืจืก:

ื‘ืึทื ื™ืฆืขืจ ืฉื™ื™ึทืŸ
ืจืขื’ื™ืกื˜ืจืึทืฆื™ืข ื˜ืึธื’

1
2019-01-01

2
2019-02-01

3
2019-02-10

4
2019-03-01

ืงืึธืกื˜ ื˜ื™ืฉ - ื‘ื™ืœื™ื ื’:

ื‘ืึทื ื™ืฆืขืจ ืฉื™ื™ึทืŸ
ื“ืึทื˜ืข
ืกืึทื›ืึทืงืœ

1
2019-01-02
11

1
2019-02-22
11

2
2019-02-12
12

3
2019-02-11
13

3
2019-03-11
13

4
2019-03-01
14

4
2019-03-02
14

ืื•ื™ืกืงืœื™ื™ึทื‘ืŸ ืึทืœืข ื‘ืึทื ื™ืฆืขืจ ืฉืจื™ื™ื‘ืŸ-ืึธืคืก ืื•ืŸ ืจืขื’ื™ืกื˜ืจืึทืฆื™ืข ื˜ืึธื’:

SELECT 
  b.userId, 
  b.Date,
  u.RegistrationDate
FROM billing AS b LEFT JOIN users AS u ON b.userId = u.userId

ื“ืขืจ ืจืขื–ื•ืœื˜ืึทื˜:

ื‘ืึทื ื™ืฆืขืจ ืฉื™ื™ึทืŸ
ื“ืึทื˜ืข
ืจืขื’ื™ืกื˜ืจืึทืฆื™ืข ื˜ืึธื’

1
2019-01-02
2019-01-02

1
2019-02-22
2019-01-02

2
2019-02-12
2019-02-01

3
2019-02-11
2019-02-10

3
2019-03-11
2019-02-10

4
2019-03-01
2019-03-01

4
2019-03-02
2019-03-01

ืžื™ืจ ื‘ื•ื™ืขืŸ ืงืึธื”ืึธืจืฅ ื“ื•ืจืš ื—ื•ื“ืฉ; ืฆื• ื˜ืึธืŸ ื“ืึธืก, ืžื™ืจ ืงืึธื ื•ื•ืขืจื˜ ืึทืœืข ื“ืึทื˜ืขืก ืื™ืŸ ื—ื“ืฉื™ื:

DATE_FORMAT(Date, '%Y-%m')

ืื™ืฆื˜ ืžื™ืจ ื“ืึทืจืคึฟืŸ ืฆื• ื•ื•ื™ืกืŸ ื•ื•ื™ ืคื™ืœืข ื—ื“ืฉื™ื ื“ืขืจ ื‘ืึทื ื™ืฆืขืจ ืื™ื– ื’ืขื•ื•ืขืŸ ืึทืงื˜ื™ื•ื• - ื“ืึธืก ืื™ื– ื“ืขืจ ื—ื™ืœื•ืง ืฆื•ื•ื™ืฉืŸ ื“ื™ ื—ื•ื“ืฉ ืคื•ืŸ ื“ืขื‘ื™ื˜ ืื•ืŸ ื“ื™ ื—ื•ื“ืฉ ืคื•ืŸ ืจืขื’ื™ืกื˜ืจืึทืฆื™ืข. MySQL ื”ืื˜ ืึท ืคื•ื ืงืฆื™ืข PERIOD_DIFF () - ื“ื™ ื—ื™ืœื•ืง ืฆื•ื•ื™ืฉืŸ ืฆื•ื•ื™ื™ ื—ื“ืฉื™ื. ืœื™ื™ื’ PERIOD_DIFF() ืฆื• ื“ืขืจ ื‘ืงืฉื”:

SELECT
    b.userId,
    DATE_FORMAT(b.Date, '%Y-%m') AS BillingMonth,
    DATE_FORMAT(u.RegistrationDate, '%Y-%m') AS RegistrationMonth,
    PERIOD_DIFF(DATE_FORMAT(b.Date, '%Y%m'), DATE_FORMAT(u.RegistrationDate, '%Y%m')) AS MonthsDiff
FROM billing AS b LEFT JOIN users AS u ON b.userId = u.userId

ื‘ืึทื ื™ืฆืขืจ ืฉื™ื™ึทืŸ
ื‘ื™ืœื™ื ื’ ืžืึธื ื˜ื”
ืจืขื’ื™ืกื˜ืจืึทืฆื™ืข ื˜ืึธื’
MonthsDiff

1
2019-01
2019-01
0

1
2019-02
2019-01
1

2
2019-02
2019-02
0

3
2019-02
2019-02
0

3
2019-03
2019-02
1

4
2019-03
2019-03
0

4
2019-03
2019-03
0

ืžื™ืจ ืฆื™ื™ืœืŸ ื“ื™ ื™ื•ื–ืขืจื– ืึทืงื˜ื™ื•ื•ื™ื™ื˜ื™ื“ ืื™ืŸ ื™ืขื“ืขืจ ื—ื•ื“ืฉ - ืžื™ืจ ื’ืจื•ืคึผืข ื“ื™ ืจืขืงืึธืจื“ืก ื“ื•ืจืš BillingMonth, RegistrationMonth ืื•ืŸ MonthsDiff:

SELECT
    COUNT(DISTINCT(b.userId)) AS UsersCount,
    DATE_FORMAT(b.Date, '%Y-%m') AS BillingMonth,
    DATE_FORMAT(u.RegistrationDate, '%Y-%m') AS RegistrationMonth,
    PERIOD_DIFF(DATE_FORMAT(b.Date, '%Y%m'), DATE_FORMAT(u.RegistrationDate, '%Y%m')) AS MonthsDiff
FROM billing AS b LEFT JOIN users AS u ON b.userId = u.userId
GROUP BY BillingMonth, RegistrationMonth, MonthsDiff

ื“ืขืจ ืจืขื–ื•ืœื˜ืึทื˜:

UsersCount
ื‘ื™ืœื™ื ื’ ืžืึธื ื˜ื”
ืคืึทืจืฉืจื™ื™ื‘ื•ื ื’ ืžืึธื ื˜ื”
MonthsDiff

1
2019-01
2019-01
0

1
2019-02
2019-01
1

2
2019-02
2019-02
0

1
2019-03
2019-02
1

1
2019-03
2019-03
0

ืื™ืŸ ื™ืื ื•ืืจ, ืคืขื‘ืจื•ืืจ ืื•ืŸ ืžืึทืจืฅ, ืื™ื™ื ืขืจ ื ื™ื™ึท ื‘ืึทื ื™ืฆืขืจ ืืจื•ื™ืก ื™ืขื“ืขืจ - MonthsDiff = 0. ืื™ื™ืŸ ื™ืื ื•ืืจ ื‘ืึทื ื™ืฆืขืจ ืื™ื– ืึทืงื˜ื™ื•ื• ืื™ืŸ ืคืขื‘ืจื•ืืจ - ืจืขื’ื™ืกื˜ืจืึทื˜ื™ืึธืŸ ืžืึธื ื˜ื” = 2019-01, BillingMonth = 2019-02, ืื•ืŸ ืื™ื™ืŸ ืคืขื‘ืจื•ืืจ ื‘ืึทื ื™ืฆืขืจ ืื™ื– ืึทืงื˜ื™ื•ื• ืื™ืŸ ืžืึทืจืฅ.

ื’ืขื•ื•ื™ื™ื ื˜ืœืขืš, ืคึผืึทื˜ืขืจื ื– ื–ืขื ืขืŸ ื‘ืขืกืขืจ ืงืขื ื˜ื™ืง ืื™ืŸ ืึท ื’ืจื•ื™ืก ื“ืึทื˜ืŸ ืฉื˜ืขืœืŸ.

ื•ื•ื™ ืฆื• ืึทืจื™ื‘ืขืจืคื™ืจืŸ ืงืึธื”ืึธืจืฅ ืฆื• Grafana

ืžื™ืจ ื”ืึธื‘ืŸ ื’ืขืœืขืจื ื˜ ื•ื•ื™ ืฆื• ืžืึทื›ืŸ ืงืึธื”ืึธืจื˜ืŸ, ืึธื‘ืขืจ ื•ื•ืขืŸ ืขืก ื–ืขื ืขืŸ ืึท ืคึผืœืึทืฅ ืคื•ืŸ ืจืขืงืึธืจื“ืก, ืขืก ืื™ื– ื ื™ืฉื˜ ื’ืจื™ื ื’ ืฆื• ืึทื ืึทืœื™ื™ื– ื–ื™ื™. ืจืขืงืึธืจื“ืก ืงืขื ืขืŸ ื–ื™ื™ืŸ ื™ืงืกืคึผืึธืจื˜ืึทื“ ืฆื• ืขืงืกืกืขืœ ืื•ืŸ ื’ืขืฉืืคืŸ ืื™ืŸ ืฉื™ื™ืŸ ื˜ื™ืฉืŸ, ืึธื‘ืขืจ ื“ืึธืก ืื™ื– ื ื™ืฉื˜ ืื•ื ื“ื–ืขืจ ืื•ืคึฟืŸ!

ืงืึธื”ืึธืจืฅ ืงืขื ืขืŸ ื–ื™ื™ืŸ ื’ืขื•ื•ื™ื–ืŸ ื•ื•ื™ ืึท ื™ื ื˜ืขืจืึทืงื˜ื™ื•ื• ื’ืจืึทืคื™ืง ืื™ืŸ ื’ืจืืคืื ื.

ืฆื• ื˜ืึธืŸ ื“ืึธืก, ืžื™ืจ ืœื™ื™ื’ืŸ ืืŸ ืื ื“ืขืจ ืึธื ืคึฟืจืขื’ ืฆื• ื’ืขืจ ื“ื™ ื“ืึทื˜ืŸ ืื™ืŸ ืึท ืคึฟืึธืจืžืึทื˜ ืคึผืึทืกื™ืง ืคึฟืึทืจ Grafana:

SELECT
  DATE_ADD(CONCAT(s.RegistrationMonth, '-01'), INTERVAL s.MonthsDiff MONTH) AS time_sec,
  SUM(s.Users) AS value,
  s.RegistrationMonth AS metric
FROM (
  ## ัั‚ะฐั€ั‹ะน ะทะฐะฟั€ะพั, ะฒะพะทะฒั€ะฐั‰ะฐัŽั‰ะธะน ะบะพะณะพั€ั‚ั‹
  SELECT 
    COUNT(DISTINCT(b.userId)) AS Users, 
    DATE_FORMAT(b.Date, '%Y-%m') AS BillingMonth,
    DATE_FORMAT(u.RegistrationDate, '%Y-%m') AS RegistrationMonth,
    PERIOD_DIFF(DATE_FORMAT(b.Date, '%Y%m'), DATE_FORMAT(u.RegistrationDate, '%Y%m')) AS MonthsDiff
  FROM billing AS b LEFT JOIN users AS u ON b.userId = u.userId
  WHERE
    u.RegistrationDate BETWEEN '2018-01-01' AND CURRENT_DATE
  GROUP BY 
    BillingMonth, RegistrationMonth, MonthsDiff 
) AS s
GROUP BY 
  time_sec, metric

ืื•ืŸ ืฆื•ืคึฟืขืœื™ืงืขืจ ื“ื™ ื“ืึทื˜ืŸ ืฆื• Grafana.

ื‘ื™ื™ึทืฉืคึผื™ืœ ื’ืจืึทืคื™ืง ืคื•ืŸ ื“ืขืžืึธ:

ื•ื•ื™ ืฆื• ื–ืึทืžืœืขืŸ ื‘ืึทื ื™ืฆืขืจ ืงืึธื”ืึธืจืฅ ื•ื•ื™ ื’ืจืึทืคืก ืื™ืŸ ื’ืจืึทืคืึทื ืึท [+ ื“ืึธืงืงืขืจ ื‘ื™ืœื“ ืžื™ื˜ ื‘ื™ื™ึทืฉืคึผื™ืœ]

ืจื™ืจ ืžื™ื˜ ื“ื™ื™ืŸ ื”ืขื ื˜:

GitHub ืจื™ืคึผืึทื–ืึทื˜ืึธืจื™ ืžื™ื˜ ื‘ื™ื™ึทืฉืคึผื™ืœ ืื™ื– ืึท ื“ืึธืงืงืขืจ ื‘ื™ืœื“ ืžื™ื˜ MySQL ืื•ืŸ Grafana ื•ื•ืึธืก ืื™ืจ ืงืขื ืขืŸ ืœื•ื™ืคืŸ ืื•ื™ืฃ ื“ื™ื™ืŸ ืงืึธืžืคึผื™ื•ื˜ืขืจ. ื“ื™ ื“ืึทื˜ืึทื‘ื™ื™ืก ืฉื•ื™ืŸ ื›ึผื•ืœืœ ื“ืขืžืึธ ื“ืึทื˜ืŸ ืคึฟืึทืจ ืึท ื™ืึธืจ ืื•ืŸ ืึท ื”ืึทืœื‘, ืคึฟื•ืŸ ื™ืื ื•ืืจ 2018 ืฆื• ื™ื•ืœื™ 2019.

ืื•ื™ื‘ ืื™ืจ ื•ื•ื™ืœื˜, ืื™ืจ ืงืขื ืขืŸ ืœืึธื“ืŸ ื“ื™ื™ืŸ ื“ืึทื˜ืŸ ืื™ืŸ ื“ืขื ื‘ื™ืœื“.

ืคึผืก ืืจื˜ื™ืงืœืขืŸ ื•ื•ืขื’ืŸ ืงืึธื”ืึธืจื˜ ืึทื ืึทืœื™ืกื™ืก ืื™ืŸ SQL:

https://chartio.com/resources/tutorials/performing-cohort-analysis-using-mysql/

https://www.holistics.io/blog/calculate-cohort-retention-analysis-with-sql/

ืžืงื•ืจ: www.habr.com

ืœื™ื™ื’ืŸ ืึท ื‘ืึทืžืขืจืงื•ื ื’