Может ли Spark SQL не считать правильно или Я не могу написать SQL правильно?


В записной книжке Python на Databricks "Community Edition" я экспериментирую с открытыми данными города Сан-Франциско об экстренных вызовах в 911 с запросом пожарных. (Старая копия данных 2016 года, используемая в "использование Apache Spark 2.0 для анализа открытых данных города Сан-Франциско" (YouTube) и доступная на S3 для этого учебника.)

После монтирования данных и чтения их с явно определенной схемой в фрейм данных fire_service_calls_df, я присвоил этому фрейму псевдоним Таблица SQL:

sqlContext.registerDataFrameAsTable(fire_service_calls_df, "fireServiceCalls")

С помощью этого и API DataFrame я могу подсчитать типы вызовов, которые произошли:

fire_service_calls_df.select('CallType').distinct().count()
Out[n]: 34

... или с SQL в Python:

spark.sql("""
SELECT count(DISTINCT CallType)
FROM fireServiceCalls
""").show()
+------------------------+
|count(DISTINCT CallType)|
+------------------------+
|                      33|
+------------------------+

... или с ячейкой SQL:

%sql

SELECT count(DISTINCT CallType)
FROM fireServiceCalls

Почему я получаю два разных результата подсчета? (похоже, что 34 является правильным, хотя разговор в видео и сопровождающей учебник тетради упоминают "35".)

1 5

1 ответ:

Чтобы ответить на вопрос

Может ли Spark SQL не считать правильно или Я не могу написать SQL правильно?

Из названия: я не могу написать SQL правильно.

Правило написания SQL: подумайте о NULL и UNDEFINED.

%sql
SELECT count(*)
FROM (
  SELECT DISTINCT CallType
  FROM fireServiceCalls 
)

34

Кроме того, я, по-видимому, не могу читать:

Поль предложил в комментарии

Имея всего 30 значений something, вы можете просто отсортировать и распечатать все различные элементы, чтобы увидеть, где разница.

Ну, вообще-то я и сам об этом думал. (Минус сортировка.) За исключением того, что не было никакой разницы, в выводе всегда было 34 типа вызовов, независимо от того, сгенерировал ли я его с помощью запросов SQL или DataFrame. Я просто не заметил, что один из них был зловеще назван null:
+--------------------------------------------+
|CallType                                    |
+--------------------------------------------+
|Elevator / Escalator Rescue                 |
|Marine Fire                                 |
|Aircraft Emergency                          |
|Confined Space / Structure Collapse         |
|Administrative                              |
|Alarms                                      |
|Odor (Strange / Unknown)                    |
|Lightning Strike (Investigation)            |
|null                                        |
|Citizen Assist / Service Call               |
|HazMat                                      |
|Watercraft in Distress                      |
|Explosion                                   |
|Oil Spill                                   |
|Vehicle Fire                                |
|Suspicious Package                          |
|Train / Rail Fire                           |
|Extrication / Entrapped (Machinery, Vehicle)|
|Other                                       |
|Transfer                                    |
|Outside Fire                                |
|Traffic Collision                           |
|Assist Police                               |
|Gas Leak (Natural and LP Gases)             |
|Water Rescue                                |
|Electrical Hazard                           |
|High Angle Rescue                           |
|Structure Fire                              |
|Industrial Accidents                        |
|Medical Incident                            |
|Mutual Aid / Assist Outside Agency          |
|Fuel Spill                                  |
|Smoke Investigation (Outside)               |
|Train / Rail Incident                       |
+--------------------------------------------+