Mysql
 sql >> база данни >  >> RDS >> Mysql

Преброяване на активните потребители с помощта на клеймо за време за влизане в MySQL

Ще демонстрирам такава идея въз основа на това, което има най-голям смисъл за мен и начина, по който бих отговорил, ако въпросът беше представен по същия начин като тук:

Първо, нека приемем набор от данни като такъв, ще назовем таблицата logins :

+---------+---------------------+
| user_id |   login_timestamp   |
+---------+---------------------+
|       1 | 2015-09-29 14:05:05 |
|       2 | 2015-09-29 14:05:08 |
|       1 | 2015-09-29 14:05:12 |
|       4 | 2015-09-22 14:05:18 |
|   ...   |          ...        |
+---------+---------------------+

Може да има и други колони, но ние нямаме нищо против тях.

Първо трябва да определим границите на тази седмица, за това можем да използваме ADDDATE() . В комбинация с идеята, че днешната дата-днешният ден от седмицата (DAYOFWEEK() на MySQL ), е датата неделя.

Например:Ако днес е сряда, 10-ти, Wed - 3 = Sun , следователно 10 - 3 = 7 и можем да очакваме неделя да бъде 7-ми.

Можем да получим WeekStart и WeekEnd времеви отпечатъци по този начин:

SELECT
DATE_FORMAT(ADDDATE(CURDATE(), INTERVAL 1-DAYOFWEEK(CURDATE()) DAY), "%Y-%m-%d 00:00:00") WeekStart, 
DATE_FORMAT(ADDDATE(CURDATE(), INTERVAL 7-DAYOFWEEK(CURDATE()) DAY), "%Y-%m-%d 23:59:59") WeekEnd;

Забележка:в PostgreSQL има DATE_TRUNC() функция, която връща началото на определена времева единица, дадена дата, като начало на седмица, месец, час и т.н. Но това не е налично в MySQL.

След това нека използваме WeekStart и weekEnd, за да разделим нашия набор от данни, в този пример просто ще покажа как да филтрирам, използвайки твърдо кодирани дати:

SELECT *
FROM `logins`
WHERE login_timestamp BETWEEN '2015-09-29 14:05:07' AND '2015-09-29 14:05:13'

Това трябва да върне нашия набор от данни нарязан, само с подходящи резултати:

+---------+---------------------+
| user_id |   login_timestamp   |
+---------+---------------------+
|       2 | 2015-09-29 14:05:08 |
|       1 | 2015-09-29 14:05:12 |
+---------+---------------------+

След това можем да намалим набора от резултати само до user_id s и филтрирайте дубликати. след това пребройте по този начин:

SELECT COUNT(DISTINCT user_id)
FROM `logins`
WHERE login_timestamp BETWEEN '2015-09-29 14:05:07' AND '2015-09-29 14:05:13'

DISTINCT ще филтрира дубликатите и count ще върне само сумата.

Комбинирано това става:

SELECT COUNT(DISTINCT user_id)
FROM `logins`
WHERE login_timestamp 
    BETWEEN DATE_FORMAT(ADDDATE(CURDATE(), INTERVAL 1- DAYOFWEEK(CURDATE()) DAY), "%Y-%m-%d 00:00:00") 
        AND DATE_FORMAT(ADDDATE(CURDATE(), INTERVAL 7- DAYOFWEEK(CURDATE()) DAY), "%Y-%m-%d 23:59:59")

Заменете CURDATE() с произволно времево клеймо, за да получите броя на потребителските влизания за тази седмица.

Но трябва да разделя това на дни, чувам те да плачеш. Разбира се! и ето как:

Първо, нека преведем нашите прекалено информативни времеви отпечатъци само в данните за датата. Добавяме DISTINCT защото нямаме нищо против един и същи потребител да влезе два пъти в един и същи ден. ние броим потребители, а не влизания, нали? (обърнете внимание, че се отдръпваме тук):

SELECT DISTINCT user_id, DATE_FORMAT(login_timestamp, "%Y-%m-%d")
FROM `logins`

Това дава:

+---------+-----------------+
| user_id | login_timestamp |
+---------+-----------------+
|       1 | 2015-09-29      |
|       2 | 2015-09-29      |
|       4 | 2015-09-22      |
|   ...   |        ...      |
+---------+-----------------+

Тази заявка ще завършим с втора, за да преброим появяванията на всяка дата:

SELECT `login_timestamp`, count(*) AS 'count'
FROM (SELECT DISTINCT user_id, DATE_FORMAT(login_timestamp, "%Y-%m-%d") AS `login_timestamp` FROM `logins`) `loginsMod`
GROUP BY `login_timestamp`

Използваме брой и групиране, за да получим списъка по дата, което връща:

+-----------------+-------+
| login_timestamp | count |
+-----------------+-------+
| 2015-09-29      | 1     +
| 2015-09-22      | 2     +
+-----------------+-------+

И след цялата упорита работа, и двете заедно:

SELECT `login_timestamp`, COUNT(*)
FROM (
SELECT DISTINCT user_id, DATE_FORMAT(login_timestamp, "%Y-%m-%d") AS `login_timestamp`
FROM `logins`
WHERE login_timestamp BETWEEN DATE_FORMAT(ADDDATE(CURDATE(), INTERVAL 1- DAYOFWEEK(CURDATE()) DAY), "%Y-%m-%d 00:00:00") AND DATE_FORMAT(ADDDATE(CURDATE(), INTERVAL 7- DAYOFWEEK(CURDATE()) DAY), "%Y-%m-%d 23:59:59")) `loginsMod`
GROUP BY `login_timestamp`;

Ще ви даде дневна разбивка на влизанията на ден през тази седмица. Отново заменете CURDATE() за да получите различна седмица.

Що се отнася до самите потребители, които са влезли, нека комбинираме същите неща в различен ред:

SELECT `user_id`
FROM (
    SELECT `user_id`, COUNT(*) AS `login_count`
    FROM (
        SELECT DISTINCT `user_id`, DATE_FORMAT(`login_timestamp`, "%Y-%m-%d")
        FROM `logins`) `logins`
    GROUP BY `user_id`) `logincounts`
WHERE `login_count` > 6

Имам две вътрешни заявки, първата е logins :

SELECT DISTINCT `user_id`, DATE_FORMAT(`login_timestamp`, "%Y-%m-%d")
FROM `logins`

Ще предостави списъка с потребители и дните, в които са влезли, без дубликати.

След това имаме logincounts :

SELECT `user_id`, COUNT(*) AS `login_count`
FROM `logins` -- See previous subquery.
GROUP BY `user_id`) `logincounts`

Ще върне същия списък, с брой влизания на всеки потребител.

И накрая:ИЗБЕРЕТЕ user_id ОТ logincounts -- Вижте предишната подзаявка. WHERE login_count> 6

Филтриране на онези, които не са влезли 7 пъти, и премахване на колоната с дата.

Това доста стана дълго, но мисля, че е пълно с идеи и мисля, че определено може да помогне да се отговори по интересен начин на работно интервю. :)



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Колко лошо е използването на SELECT MAX(id) в MYSQL вместо mysql_insert_id() в PHP?

  2. Грешка в MySQL/Amazon RDS:нямате СУПЕР привилегии...

  3. Как да групирате непрекъснати диапазони с MySQL

  4. как да преброите появата на дума в няколко реда на mysql db

  5. Мога ли да направя колоните на mysql таблицата нечувствителни към главни букви?