# HAVING

Вернёмся к нашей таблице **data\_analyzer.diagnosis\_dst\_meta** из предыдущего примера. Добавим группировку по ключу партиционирования и отфильтруем данные двумя способами:

```sql
SELECT toYYYYMM(signed_dt), count() as cnt
FROM data_analyzer.diagnosis_dst_meta
GROUP BY toYYYYMM(signed_dt)
HAVING toYYYYMM(signed_dt) IN (202501, 202502, 202503)
```

```sql
SELECT toYYYYMM(signed_dt), count() as cnt FROM data_analyzer.diagnosis_dst_meta
WHERE toYYYYMM(signed_dt) IN (202501, 202502, 202503)
GROUP BY toYYYYMM(signed_dt)
```

По логике в первом запросе сначала читается вся таблица, затем происходит группировка, затем фильтрация по агрегированному полю. Во втором запросе читаются только нужные партиции и кажется, что он существенно оптимальнее по производительности. Проверим:

<figure><img src="https://2436045964-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FCZ9JZpjgSMxqwUmrf0Bd%2Fuploads%2FWhhUKG9sZeRqNjVXsI1G%2Fimage.png?alt=media&#x26;token=6279a451-a8c4-43d1-9858-092b3d9e4bbb" alt=""><figcaption><p>Результаты</p></figcaption></figure>

Мы видим, что результаты практически идентичны (только незначительное различие по памяти). Это произошло, потому что на самом деле **первый запрос не был выполнен, как мы его задумали**, а был оптимизирован кликхаусом ([тут мы обсуждаем эту оптимизацию](https://um-dzm.gitbook.io/ch_optimize/pod-kapotom#vstroennyi-optimizitor)). Давайте в этом убедимся при помощи оператора **EXPLAIN SYNTAX** — эта конструкция показывает, как выглядит запрос после внутренней оптимизаци&#x438;**:**

```sql
EXPLAIN SYNTAX SELECT toYYYYMM(signed_dt), count() as cnt
FROM data_analyzer.diagnosis_dst_meta
GROUP BY toYYYYMM(signed_dt)
HAVING toYYYYMM(signed_dt) IN (202501, 202502, 202503)

EXPLAIN SYNTAX SELECT toYYYYMM(signed_dt), count() as cnt
FROM data_analyzer.diagnosis_dst_meta
WHERE toYYYYMM(signed_dt) IN (202501, 202502, 202503)
GROUP BY toYYYYMM(signed_dt)
```

<figure><img src="https://2436045964-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FCZ9JZpjgSMxqwUmrf0Bd%2Fuploads%2FSUihHiJhz1cxbZaxM7WN%2Fimage.png?alt=media&#x26;token=68aa6705-b19d-406f-864c-82b19676b84f" alt=""><figcaption><p>Один результат в обоих случаях</p></figcaption></figure>

Несмотря на то, что кликхаус исправляет такие ошибки пользователя, происходит это не всегда и спрогнозировать работу оптимизатора невозможно. Поэтому правильно использовать **WHERE** вместо **HAVING** если это возможно

## Выводы

* Не используйте HAVING там, где можно обойтись WHERE
* Используйте EXPLAIN SYNTAX, чтобы увидеть, как запрос выглядит после обработки оптимизатором


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://um-dzm.gitbook.io/ch_optimize/optimizaciya/having.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
