Запросите макс. количество одновременных событий

Прежде всего вам нужно несколько новых переменных:

enum FilterType { // you can add here any filter options you want
        case allUsers, active, inactive
    }

var users = [User]()
var activeUsers = [User]()
var inactiveUsers = [User]()
var filterType = FilterType.allUsers

После этого отредактируйте метод numberOfRowInSection:

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        switch filterType {
        case .allUsers:
            return users
        case .active:
            return activeUsers
        case .inactive:
            return inactiveUsers
        }
}

И не забудьте добавить tableView.reloadData() в конец действия вашей кнопки:

@IBAction func ActionShowActiveUsers(_ sender: Any) {
        let activeUser =  users.filter( { return [112].active == true } )
        print(activeUser.count)
        filterType = .active
        tableView.reloadData()
    }

@IBAction func btnShowInActiveUser(_ sender: Any) {
        let inactiveUser =  users.filter( { return [112].active == false } )
        print(inactiveUser.count)
        filterType = .inactive
        tableView.reloadData()
}
5
задан 17 January 2009 в 00:06
поделиться

4 ответа

Мой ответ очень похож на первый ответ Harry's. Я попытался бы сделать немного отличающуюся оптимизацию производительности хотя... Пропустите в конец для предотвращения хаотичного объяснения почему...

Первый ответ Harry's (Логика ядра)

SELECT MAX(overlapAtEnd)
FROM
(
    SELECT 
        COUNT(1) AS overlapAtEnd                        
    FROM 
        your_table AS t1, 
        your_table AS t2
    WHERE 
        t1.end_time BETWEEN t2.start_time AND t2.end_time
    GROUP BY t1.event_id
) AS foo

Место, которое занимает большую часть времени обработки, является соединением.

Для каждой записи в таблице Вы выбираете (t1.end время). Вы затем ищете таблицу снова (t1.end_time> = start_time), и все соответствие записывает Вас поиск (t1.end_time <= t1.end_time)

Теперь, для Вас очень легко создать индекс на start_time. Это осуществляет первую проверку (t1.end_time> = start_time) намного быстрее;
- Индекс является деревом поиска для чрезвычайно быстрого поиска
- Это делает нахождение первой записи соответствия очень быстрым
- Индекс по существу заказан
- Это означает, что знает "все после того, как первое соответствие также соответствует"

Последняя часть, хотя является ключевым, потому что это означает это... Даже после использования индекса, чтобы сделать первую проверку (t1.end_time> = start_time) нас можно все еще оставить с большим количеством записей осуществить вторую проверку (t1.end_time <= t1.end_time)

[включая end_time в индексе не помогает здесь и обсужден вскоре]

0, '10:00', '10:04'   COUNT(*) WHERE '10:04' >= start_time  ==  4
1, '10:01', '10:06'   COUNT(*) WHERE '10:06' >= start_time  ==  4
2, '10:02', '10:09'   COUNT(*) WHERE '10:09' >= start_time  ==  5
3, '10:04', '10:07'   COUNT(*) WHERE '10:07' >= start_time  ==  4
4, '10:08', '10:12'   COUNT(*) WHERE '10:12' >= start_time  ==  6
5, '10:12', '10:17'   COUNT(*) WHERE '10:17' >= start_time  ==  7
6, '10:15', '10:18'   COUNT(*) WHERE '10:18' >= start_time  ==  8
7, '10:18', '10:22'   COUNT(*) WHERE '10:22' >= start_time  ==  10
8, '10:19', '10:24'   COUNT(*) WHERE '10:24' >= start_time  ==  10
9, '10:22', '10:25'   COUNT(*) WHERE '10:25' >= start_time  ==  10

=> leaves 68 rows to check the second condition; (t1.end_time <= t1.end_time)

Принимая относительно гладкое распределение событий, каждая запись была бы (приблизительно и в среднем) соответствие с половиной таблицы. Это означает выполнение (n*n/2) проверок, где n является количеством записей в таблице. Даже в 100 записях это дает 5 000 проверок. В 2 000 записей Вы делаете приблизительно 2 миллиона проверок!

Естественный наклон состоит в том, чтобы добавить end_time поле к индексу. Это не помогает, как бы то ни было. Индекс для (start_time, end_time) создает дерево поиска вниз к каждому уникальному start_time, затем под каждым уникальным start_time существует отдельное дерево поиска для end_times.

В моем примере выше, каждый start_time уникален. Это означает, что все еще необходимо сделать все 68 проверок end_time. Только проверки start_time, которым извлекают выгоду из индекса.

То, что мы должны сделать, попытаться использовать единственный индекс "start_time", чтобы сделать больше, чем мы в настоящее время. Мы должны дать механизму запроса больше информации.

Пример состоит в том, чтобы использовать "максимальную продолжительность события". Например, мы можем найти, что никакое событие не длится дольше, чем 8 минут. Это дало бы нам следующий запрос...

SELECT MAX(overlapAtEnd)
FROM
(
    SELECT 
        COUNT(1) AS overlapAtEnd                        
    FROM 
        your_table AS t1, 
        your_table AS t2
    WHERE 
            t1.end_time >= t2.start_time
        AND t1.end_time <= t2.end_time
        AND t1.end_time <= t2.start_time + [max_event_duration] 
    GROUP BY t1.event_id
) AS foo

Применение примера 8-минутной продолжительности на примере, который я дал выше, мы уменьшаем 68 проверок end_time вниз до 34.

0, '10:00', '10:04'   COUNT(*) WHERE '10:04' BETWEEN start_time AND start_time + 8 == 4
1, '10:01', '10:06'   COUNT(*) WHERE '10:06' BETWEEN start_time AND start_time + 8 == 4
2, '10:02', '10:09'   COUNT(*) WHERE '10:09' BETWEEN start_time AND start_time + 8 == 4
3, '10:04', '10:07'   COUNT(*) WHERE '10:07' BETWEEN start_time AND start_time + 8 == 4
4, '10:08', '10:12'   COUNT(*) WHERE '10:12' BETWEEN start_time AND start_time + 8 == 3
5, '10:12', '10:17'   COUNT(*) WHERE '10:17' BETWEEN start_time AND start_time + 8 == 2
6, '10:15', '10:18'   COUNT(*) WHERE '10:18' BETWEEN start_time AND start_time + 8 == 3
7, '10:18', '10:22'   COUNT(*) WHERE '10:22' BETWEEN start_time AND start_time + 8 == 4
8, '10:19', '10:24'   COUNT(*) WHERE '10:24' BETWEEN start_time AND start_time + 8 == 3
9, '10:22', '10:25'   COUNT(*) WHERE '10:25' BETWEEN start_time AND start_time + 8 == 3

=> leaves 34 rows to check the second condition; (t1.end_time <= t1.end_time)
=> thats half the original 68, and on bigger tables the benefit increases...

Даже если мы не знали, что события никогда не длинны, чем 8 минут, мы, возможно, нашли его только путем проверки 10 записей. МАКС (end_time - start_time) более чем 10 записей все еще был бы быстрее, чем проверка (t1.end_time <= t1.end_time) более чем 34 комбинации записей.

И поскольку размер таблицы увеличивается, увеличения преимущества. На самом деле, где [max_event_duration] значительно меньше, чем промежуток всего времени, покрытый таблицей, Вы изменяете (nn/2) квадратичный закон во что-то намного больше как (nx + n), который линеен.

Демократы.

SELECT
   MAX(overlapAtEnd)
FROM
(
    SELECT 
        COUNT(1) AS overlapAtEnd                        
    FROM 
        your_table AS t1, 
        your_table AS t2
    WHERE 
            t2.start_time <= t1.end_time
        AND t2.start_time >= t1.end_time - (SELECT MAX(end_time - start_time) FROM your_table)
        AND t2.end_time   >= t1.end_time
    GROUP BY t1.event_id
) AS foo
4
ответ дан 14 December 2019 в 13:49
поделиться

В зависимости от того, под чем Вы подразумеваете одновременный, как отмечено другими ответами, это может быть очень похоже на этот вопрос.

К сожалению, решение, которое я предложил (который был принятым ответом) потребует, чтобы Вы перепроектировали свою таблицу. Однако это позволит Вам тривиально определить максимальное количество одновременных событий путем исследования "SessionCount" (или так же названный) столбец.

2
ответ дан 14 December 2019 в 13:49
поделиться

Я сделал бы это во многих передачах, очень медленном решении, но не может быть очень быстрого способа сделать это. и решение на основе ответа Daniel Paull было бы намного быстрее.

Отсортируйте свои события ко времени начала. Цикл через события и находит разрывы, в которых нет никаких событий, событий группы между этими разрывами. Цикл в течение каждого раза, когда (в любом разрешении Ваши времена зарегистрированы в) в каждой группе и запрашивает события, которые продолжаются в то время. В зависимости от скорости Вашего языка программирования по сравнению со скоростью запросов DB можно посмотреть на перекрывающиеся события и пропустить вперед к первому end_time одного из перекрывающихся событий.

0
ответ дан 14 December 2019 в 13:49
поделиться

Так как Ваше пиковое время будет всегда заканчиваться на end_time, можно просто проверить те времена отчасти как предложенный Sparr. Также - запрос, чтобы присоединиться к той же таблице дважды и считать количество строк, где событие накладывается в каждом end_time. Затем возьмите макс. из этого.

Это будет давать Вам Ваш ответ, но медленно:

SELECT MAX(overlapAtEnd)
FROM
(
    SELECT 
        COUNT(1) AS overlapAtEnd            
    FROM 
        your_table AS t1, 
        your_table AS t2
    WHERE 
        t1.end_time BETWEEN t2.start_time AND t2.end_time
    GROUP BY t1.event_id
) AS foo

Разбивание его в меньшие группы (меньше для сравнения с), затем получение макс. из тех меньших групп значительно ускоряют его:

SELECT MAX(maxOLP)
FROM
(
    SELECT MAX(olp) AS maxOLP
    FROM
    (
        SELECT 
            MAX(overlapAtEnd) AS maxOLP,
            EXTRACT(HOUR FROM t1.end_time)  AS hr
        FROM
        (
            SELECT 
                COUNT(1) AS overlapAtEnd            
            FROM 
                your_table AS t1, 
                your_table AS t2
            WHERE 
                t1.end_time BETWEEN t2.start_time AND t2.end_time
            GROUP BY t1.event_id
        ) AS foo
        GROUP BY t1.event_id, EXTRACT(HOUR FROM t1.end_time)
    ) AS foo
    GROUP BY hr
) AS foo2

Существует небольшой недостаток к этому более быстрому подходу..., если Ваши события обычно охватывают больше чем час события, которые заканчиваются в следующий час, может все еще наложиться, но привычка считаться. Зафиксировать это, просто группа большим интервалом как день или неделя. Довольно волосатый, но это работает отлично и быстро дает Вам результат, это кажется, что Вы ищете.

0
ответ дан 14 December 2019 в 13:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: