> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-mintlify-fbfa8bee.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> مجموعة بيانات تضم 1.3 مليون سجل من البيانات التاريخية عن قوائم طعام الفنادق والمطاعم والمقاهي، بما في ذلك الأطباق وأسعارها.

# مجموعة بيانات "What's on the Menu?" لمكتبة نيويورك العامة

أعدّت مكتبة نيويورك العامة مجموعة البيانات هذه. وهي تضم بيانات تاريخية عن قوائم طعام الفنادق والمطاعم والمقاهي، بما في ذلك الأطباق وأسعارها.

المصدر: [http://menus.nypl.org/data](http://menus.nypl.org/data)
البيانات متاحة ضمن الملك العام.

البيانات مأخوذة من أرشيف المكتبة، وقد تكون غير مكتملة ويصعب استخدامها في التحليل الإحصائي. ومع ذلك، فهي شهية جدًا أيضًا.
الحجم لا يتجاوز 1.3 مليون سجل عن الأطباق في قوائم الطعام — وهو حجم بيانات صغير جدًا بالنسبة إلى ClickHouse، لكنه يظل مثالًا جيدًا.

<div id="download-dataset">
  ## نزّل مجموعة البيانات
</div>

نفّذ الأمر:

```bash theme={null}
wget https://s3.amazonaws.com/menusdata.nypl.org/gzips/2021_08_01_07_01_17_data.tgz
# Option: Validate the checksum
md5sum 2021_08_01_07_01_17_data.tgz
# Checksum should be equal to: db6126724de939a5481e3160a2d67d15
```

استبدل الرابط بالرابط المُحدَّث من [http://menus.nypl.org/data](http://menus.nypl.org/data) إذا لزم الأمر.
يبلغ حجم التنزيل نحو 35 ميغابايت.

<div id="unpack-dataset">
  ## فك ضغط مجموعة البيانات
</div>

```bash theme={null}
tar xvf 2021_08_01_07_01_17_data.tgz
```

يبلغ الحجم غير المضغوط نحو 150 ميغابايت.

البيانات مُطبَّعة وتتكوّن من أربعة جداول:

* `Menu` — معلومات عن القوائم: اسم المطعم، والتاريخ الذي ظهرت فيه القائمة، وما إلى ذلك.
* `Dish` — معلومات عن الأطباق: اسم الطبق إلى جانب بعض خصائصه.
* `MenuPage` — معلومات عن الصفحات في القوائم، لأن كل صفحة تنتمي إلى قائمة معيّنة.
* `MenuItem` — عنصر في القائمة: طبق مع سعره في صفحة قائمة معيّنة، مع روابط إلى الطبق وصفحة القائمة.

<div id="create-tables">
  ## إنشاء الجداول
</div>

نستخدم نوع البيانات [Decimal](/ar/reference/data-types/decimal) لتخزين الأسعار.

```sql theme={null}
CREATE TABLE dish
(
    id UInt32,
    name String,
    description String,
    menus_appeared UInt32,
    times_appeared Int32,
    first_appeared UInt16,
    last_appeared UInt16,
    lowest_price Decimal64(3),
    highest_price Decimal64(3)
) ENGINE = MergeTree ORDER BY id;

CREATE TABLE menu
(
    id UInt32,
    name String,
    sponsor String,
    event String,
    venue String,
    place String,
    physical_description String,
    occasion String,
    notes String,
    call_number String,
    keywords String,
    language String,
    date String,
    location String,
    location_type String,
    currency String,
    currency_symbol String,
    status String,
    page_count UInt16,
    dish_count UInt16
) ENGINE = MergeTree ORDER BY id;

CREATE TABLE menu_page
(
    id UInt32,
    menu_id UInt32,
    page_number UInt16,
    image_id String,
    full_height UInt16,
    full_width UInt16,
    uuid UUID
) ENGINE = MergeTree ORDER BY id;

CREATE TABLE menu_item
(
    id UInt32,
    menu_page_id UInt32,
    price Decimal64(3),
    high_price Decimal64(3),
    dish_id UInt32,
    created_at DateTime,
    updated_at DateTime,
    xpos Float64,
    ypos Float64
) ENGINE = MergeTree ORDER BY id;
```

<div id="import-data">
  ## استيراد البيانات
</div>

لاستيراد البيانات إلى ClickHouse، شغّل:

```bash theme={null}
clickhouse-client --format_csv_allow_single_quotes 0 --input_format_null_as_default 0 --query "INSERT INTO dish FORMAT CSVWithNames" < Dish.csv
clickhouse-client --format_csv_allow_single_quotes 0 --input_format_null_as_default 0 --query "INSERT INTO menu FORMAT CSVWithNames" < Menu.csv
clickhouse-client --format_csv_allow_single_quotes 0 --input_format_null_as_default 0 --query "INSERT INTO menu_page FORMAT CSVWithNames" < MenuPage.csv
clickhouse-client --format_csv_allow_single_quotes 0 --input_format_null_as_default 0 --date_time_input_format best_effort --query "INSERT INTO menu_item FORMAT CSVWithNames" < MenuItem.csv
```

نستخدم تنسيق [CSVWithNames](/ar/reference/formats/CSV/CSVWithNames) لأن البيانات مُمثَّلة بتنسيق CSV مع صفّ ترويسة.

نعطّل `format_csv_allow_single_quotes` لأن حقول البيانات تستخدم علامات الاقتباس المزدوجة فقط، بينما قد تظهر علامات الاقتباس المفردة داخل القيم، ويجب ألا تؤدي إلى إرباك محلّل CSV.

نعطّل [input\_format\_null\_as\_default](/ar/reference/settings/formats#input_format_null_as_default) لأن بياناتنا لا تحتوي على [NULL](/ar/reference/settings/formats#input_format_null_as_default). وإلا فسيحاول ClickHouse تحليل تسلسلات `\N`، وقد يلتبس عليه الأمر بينها وبين `\` داخل البيانات.

يتيح الإعداد [date\_time\_input\_format best\_effort](/ar/reference/settings/formats#date_time_input_format) تحليل حقول [DateTime](/ar/reference/data-types/datetime) ضمن نطاق واسع من التنسيقات. على سبيل المثال، سيتعرّف على ISO-8601 من دون ثوانٍ مثل '2000-01-01 01:02'. ومن دون هذا الإعداد، لا يُسمح إلا بتنسيق DateTime ثابت.

<div id="denormalize-data">
  ## إلغاء تطبيع البيانات
</div>

تُعرض البيانات في عدة جداول بصيغة [صيغة مُطبَّعة](https://en.wikipedia.org/wiki/Database_normalization#Normal_forms). وهذا يعني أنك تحتاج إلى تنفيذ [JOIN](/ar/reference/statements/select/join) إذا كنت تريد إجراء استعلام، مثلًا، للحصول على أسماء الأطباق من عناصر القائمة.
وبالنسبة إلى المهام التحليلية المعتادة، يكون التعامل مع البيانات المضمومة مسبقًا عبر JOIN أكثر كفاءة بكثير لتجنّب تنفيذ `JOIN` في كل مرة. ويُطلق على هذا النوع اسم البيانات "إلغاء تطبيع".

سننشئ جدولًا باسم `menu_item_denorm` يحتوي على جميع البيانات المضمومة معًا عبر JOIN:

```sql theme={null}
CREATE TABLE menu_item_denorm
ENGINE = MergeTree ORDER BY (dish_name, created_at)
AS SELECT
    price,
    high_price,
    created_at,
    updated_at,
    xpos,
    ypos,
    dish.id AS dish_id,
    dish.name AS dish_name,
    dish.description AS dish_description,
    dish.menus_appeared AS dish_menus_appeared,
    dish.times_appeared AS dish_times_appeared,
    dish.first_appeared AS dish_first_appeared,
    dish.last_appeared AS dish_last_appeared,
    dish.lowest_price AS dish_lowest_price,
    dish.highest_price AS dish_highest_price,
    menu.id AS menu_id,
    menu.name AS menu_name,
    menu.sponsor AS menu_sponsor,
    menu.event AS menu_event,
    menu.venue AS menu_venue,
    menu.place AS menu_place,
    menu.physical_description AS menu_physical_description,
    menu.occasion AS menu_occasion,
    menu.notes AS menu_notes,
    menu.call_number AS menu_call_number,
    menu.keywords AS menu_keywords,
    menu.language AS menu_language,
    menu.date AS menu_date,
    menu.location AS menu_location,
    menu.location_type AS menu_location_type,
    menu.currency AS menu_currency,
    menu.currency_symbol AS menu_currency_symbol,
    menu.status AS menu_status,
    menu.page_count AS menu_page_count,
    menu.dish_count AS menu_dish_count
FROM menu_item
    JOIN dish ON menu_item.dish_id = dish.id
    JOIN menu_page ON menu_item.menu_page_id = menu_page.id
    JOIN menu ON menu_page.menu_id = menu.id;
```

<div id="validate-data">
  ## تحقّق من البيانات
</div>

```sql title="Query" theme={null}
SELECT count() FROM menu_item_denorm;
```

```text title="Response" theme={null}
┌─count()─┐
│ 1329175 │
└─────────┘
```

<div id="run-queries">
  ## نفّذ بعض الاستعلامات
</div>

<div id="query-averaged-historical-prices">
  ### متوسط أسعار الأطباق تاريخيًا
</div>

```sql title="Query" theme={null}
SELECT
    round(toUInt32OrZero(extract(menu_date, '^\\d{4}')), -1) AS d,
    count(),
    round(avg(price), 2),
    bar(avg(price), 0, 100, 100)
FROM menu_item_denorm
WHERE (menu_currency = 'Dollars') AND (d > 0) AND (d < 2022)
GROUP BY d
ORDER BY d ASC;
```

```text title="Response" theme={null}
┌────d─┬─count()─┬─round(avg(price), 2)─┬─bar(avg(price), 0, 100, 100)─┐
│ 1850 │     618 │                  1.5 │ █▍                           │
│ 1860 │    1634 │                 1.29 │ █▎                           │
│ 1870 │    2215 │                 1.36 │ █▎                           │
│ 1880 │    3909 │                 1.01 │ █                            │
│ 1890 │    8837 │                  1.4 │ █▍                           │
│ 1900 │  176292 │                 0.68 │ ▋                            │
│ 1910 │  212196 │                 0.88 │ ▊                            │
│ 1920 │  179590 │                 0.74 │ ▋                            │
│ 1930 │   73707 │                  0.6 │ ▌                            │
│ 1940 │   58795 │                 0.57 │ ▌                            │
│ 1950 │   41407 │                 0.95 │ ▊                            │
│ 1960 │   51179 │                 1.32 │ █▎                           │
│ 1970 │   12914 │                 1.86 │ █▋                           │
│ 1980 │    7268 │                 4.35 │ ████▎                        │
│ 1990 │   11055 │                 6.03 │ ██████                       │
│ 2000 │    2467 │                11.85 │ ███████████▋                 │
│ 2010 │     597 │                25.66 │ █████████████████████████▋   │
└──────┴─────────┴──────────────────────┴──────────────────────────────┘
```

خُذه بتحفّظ.

<div id="query-burger-prices">
  ### أسعار البرغر
</div>

```sql title="Query" theme={null}
SELECT
    round(toUInt32OrZero(extract(menu_date, '^\\d{4}')), -1) AS d,
    count(),
    round(avg(price), 2),
    bar(avg(price), 0, 50, 100)
FROM menu_item_denorm
WHERE (menu_currency = 'Dollars') AND (d > 0) AND (d < 2022) AND (dish_name ILIKE '%burger%')
GROUP BY d
ORDER BY d ASC;
```

```text title="Response" theme={null}
┌────d─┬─count()─┬─round(avg(price), 2)─┬─bar(avg(price), 0, 50, 100)───────────┐
│ 1880 │       2 │                 0.42 │ ▋                                     │
│ 1890 │       7 │                 0.85 │ █▋                                    │
│ 1900 │     399 │                 0.49 │ ▊                                     │
│ 1910 │     589 │                 0.68 │ █▎                                    │
│ 1920 │     280 │                 0.56 │ █                                     │
│ 1930 │      74 │                 0.42 │ ▋                                     │
│ 1940 │     119 │                 0.59 │ █▏                                    │
│ 1950 │     134 │                 1.09 │ ██▏                                   │
│ 1960 │     272 │                 0.92 │ █▋                                    │
│ 1970 │     108 │                 1.18 │ ██▎                                   │
│ 1980 │      88 │                 2.82 │ █████▋                                │
│ 1990 │     184 │                 3.68 │ ███████▎                              │
│ 2000 │      21 │                 7.14 │ ██████████████▎                       │
│ 2010 │       6 │                18.42 │ ████████████████████████████████████▋ │
└──────┴─────────┴──────────────────────┴───────────────────────────────────────┘
```

<div id="query-vodka">
  ### فودكا
</div>

```sql title="Query" theme={null}
SELECT
    round(toUInt32OrZero(extract(menu_date, '^\\d{4}')), -1) AS d,
    count(),
    round(avg(price), 2),
    bar(avg(price), 0, 50, 100)
FROM menu_item_denorm
WHERE (menu_currency IN ('Dollars', '')) AND (d > 0) AND (d < 2022) AND (dish_name ILIKE '%vodka%')
GROUP BY d
ORDER BY d ASC;
```

```text title="Response" theme={null}
┌────d─┬─count()─┬─round(avg(price), 2)─┬─bar(avg(price), 0, 50, 100)─┐
│ 1910 │       2 │                    0 │                             │
│ 1920 │       1 │                  0.3 │ ▌                           │
│ 1940 │      21 │                 0.42 │ ▋                           │
│ 1950 │      14 │                 0.59 │ █▏                          │
│ 1960 │     113 │                 2.17 │ ████▎                       │
│ 1970 │      37 │                 0.68 │ █▎                          │
│ 1980 │      19 │                 2.55 │ █████                       │
│ 1990 │      86 │                  3.6 │ ███████▏                    │
│ 2000 │       2 │                 3.98 │ ███████▊                    │
└──────┴─────────┴──────────────────────┴─────────────────────────────┘
```

للحصول على vodka، علينا كتابة `ILIKE '%vodka%'`، وهذا بالتأكيد يبعث برسالة واضحة.

<div id="query-caviar">
  ### الكافيار
</div>

لنطبع أسعار الكافيار، ولنطبع أيضًا اسم أي طبق يحتوي على الكافيار.

```sql title="Query" theme={null}
SELECT
    round(toUInt32OrZero(extract(menu_date, '^\\d{4}')), -1) AS d,
    count(),
    round(avg(price), 2),
    bar(avg(price), 0, 50, 100),
    any(dish_name)
FROM menu_item_denorm
WHERE (menu_currency IN ('Dollars', '')) AND (d > 0) AND (d < 2022) AND (dish_name ILIKE '%caviar%')
GROUP BY d
ORDER BY d ASC;
```

```text title="Response" theme={null}
┌────d─┬─count()─┬─round(avg(price), 2)─┬─bar(avg(price), 0, 50, 100)──────┬─any(dish_name)──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ 1090 │       1 │                    0 │                                  │ Caviar                                                                                                                              │
│ 1880 │       3 │                    0 │                                  │ Caviar                                                                                                                              │
│ 1890 │      39 │                 0.59 │ █▏                               │ Butter and caviar                                                                                                                   │
│ 1900 │    1014 │                 0.34 │ ▋                                │ Anchovy Caviar on Toast                                                                                                             │
│ 1910 │    1588 │                 1.35 │ ██▋                              │ 1/1 Brötchen Caviar                                                                                                                 │
│ 1920 │     927 │                 1.37 │ ██▋                              │ ASTRAKAN CAVIAR                                                                                                                     │
│ 1930 │     289 │                 1.91 │ ███▋                             │ Astrachan caviar                                                                                                                    │
│ 1940 │     201 │                 0.83 │ █▋                               │ (SPECIAL) Domestic Caviar Sandwich                                                                                                  │
│ 1950 │      81 │                 2.27 │ ████▌                            │ Beluga Caviar                                                                                                                       │
│ 1960 │     126 │                 2.21 │ ████▍                            │ Beluga Caviar                                                                                                                       │
│ 1970 │     105 │                 0.95 │ █▊                               │ BELUGA MALOSSOL CAVIAR AMERICAN DRESSING                                                                                            │
│ 1980 │      12 │                 7.22 │ ██████████████▍                  │ Authentic Iranian Beluga Caviar the world's finest black caviar presented in ice garni and a sampling of chilled 100° Russian vodka │
│ 1990 │      74 │                14.42 │ ████████████████████████████▋    │ Avocado Salad, Fresh cut avocado with caviare                                                                                       │
│ 2000 │       3 │                 7.82 │ ███████████████▋                 │ Aufgeschlagenes Kartoffelsueppchen mit Forellencaviar                                                                               │
│ 2010 │       6 │                15.58 │ ███████████████████████████████▏ │ "OYSTERS AND PEARLS" "Sabayon" of Pearl Tapioca with Island Creek Oysters and Russian Sevruga Caviar                                │
└──────┴─────────┴──────────────────────┴──────────────────────────────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
```

على الأقل لديهم كافيار مع الفودكا. رائع جدًا.

<div id="playground">
  ## ساحة التجربة عبر الإنترنت
</div>

تُرفع البيانات إلى ClickHouse Playground، [مثال](https://sql.clickhouse.com?query_id=KB5KQJJFNBKHE5GBUJCP1B).
