diff --git a/homeassistant/components/recorder/statistics.py b/homeassistant/components/recorder/statistics.py
index 691fc58c6096ecd1d41c30ca7d9f7a3e98676ec5..8b434fcdf3ab3c115ff2605a59e0706cf846a5a1 100644
--- a/homeassistant/components/recorder/statistics.py
+++ b/homeassistant/components/recorder/statistics.py
@@ -241,7 +241,8 @@ def _get_statistic_to_display_unit_converter(
     statistic_unit: str | None,
     state_unit: str | None,
     requested_units: dict[str, str] | None,
-) -> Callable[[float | None], float | None] | None:
+    allow_none: bool = True,
+) -> Callable[[float | None], float | None] | Callable[[float], float] | None:
     """Prepare a converter from the statistics unit to display unit."""
     if (converter := STATISTIC_UNIT_TO_UNIT_CONVERTER.get(statistic_unit)) is None:
         return None
@@ -260,9 +261,11 @@ def _get_statistic_to_display_unit_converter(
     if display_unit == statistic_unit:
         return None
 
-    return converter.converter_factory_allow_none(
-        from_unit=statistic_unit, to_unit=display_unit
-    )
+    if allow_none:
+        return converter.converter_factory_allow_none(
+            from_unit=statistic_unit, to_unit=display_unit
+        )
+    return converter.converter_factory(from_unit=statistic_unit, to_unit=display_unit)
 
 
 def _get_display_to_statistic_unit_converter(
@@ -1760,13 +1763,11 @@ def _statistics_during_period_with_session(
 
     result = _sorted_statistics_to_dict(
         hass,
-        session,
         stats,
         statistic_ids,
         metadata,
         True,
         table,
-        start_time,
         units,
         types,
     )
@@ -1878,14 +1879,12 @@ def _get_last_statistics(
         # Return statistics combined with metadata
         return _sorted_statistics_to_dict(
             hass,
-            session,
             stats,
             statistic_ids,
             metadata,
             convert_units,
             table,
             None,
-            None,
             types,
         )
 
@@ -1993,14 +1992,12 @@ def get_latest_short_term_statistics_with_session(
     # Return statistics combined with metadata
     return _sorted_statistics_to_dict(
         hass,
-        session,
         stats,
         statistic_ids,
         metadata,
         False,
         StatisticsShortTerm,
         None,
-        None,
         types,
     )
 
@@ -2047,42 +2044,119 @@ def _statistics_at_time(
     return cast(Sequence[Row], execute_stmt_lambda_element(session, stmt))
 
 
-def _fast_build_sum_list(
-    stats_list: list[Row],
+def _build_sum_converted_stats(
+    db_rows: list[Row],
+    table_duration_seconds: float,
+    start_ts_idx: int,
+    sum_idx: int,
+    convert: Callable[[float | None], float | None] | Callable[[float], float],
+) -> list[StatisticsRow]:
+    """Build a list of sum statistics."""
+    return [
+        {
+            "start": (start_ts := db_row[start_ts_idx]),
+            "end": start_ts + table_duration_seconds,
+            "sum": None if (v := db_row[sum_idx]) is None else convert(v),
+        }
+        for db_row in db_rows
+    ]
+
+
+def _build_sum_stats(
+    db_rows: list[Row],
     table_duration_seconds: float,
-    convert: Callable | None,
     start_ts_idx: int,
     sum_idx: int,
 ) -> list[StatisticsRow]:
     """Build a list of sum statistics."""
-    if convert:
-        return [
-            {
-                "start": (start_ts := db_state[start_ts_idx]),
-                "end": start_ts + table_duration_seconds,
-                "sum": convert(db_state[sum_idx]),
-            }
-            for db_state in stats_list
-        ]
     return [
         {
-            "start": (start_ts := db_state[start_ts_idx]),
+            "start": (start_ts := db_row[start_ts_idx]),
             "end": start_ts + table_duration_seconds,
-            "sum": db_state[sum_idx],
+            "sum": db_row[sum_idx],
         }
-        for db_state in stats_list
+        for db_row in db_rows
     ]
 
 
-def _sorted_statistics_to_dict(  # noqa: C901
+def _build_stats(
+    db_rows: list[Row],
+    table_duration_seconds: float,
+    start_ts_idx: int,
+    mean_idx: int | None,
+    min_idx: int | None,
+    max_idx: int | None,
+    last_reset_ts_idx: int | None,
+    state_idx: int | None,
+    sum_idx: int | None,
+) -> list[StatisticsRow]:
+    """Build a list of statistics without unit conversion."""
+    result: list[StatisticsRow] = []
+    ent_results_append = result.append
+    for db_row in db_rows:
+        row: StatisticsRow = {
+            "start": (start_ts := db_row[start_ts_idx]),
+            "end": start_ts + table_duration_seconds,
+        }
+        if last_reset_ts_idx is not None:
+            row["last_reset"] = db_row[last_reset_ts_idx]
+        if mean_idx is not None:
+            row["mean"] = db_row[mean_idx]
+        if min_idx is not None:
+            row["min"] = db_row[min_idx]
+        if max_idx is not None:
+            row["max"] = db_row[max_idx]
+        if state_idx is not None:
+            row["state"] = db_row[state_idx]
+        if sum_idx is not None:
+            row["sum"] = db_row[sum_idx]
+        ent_results_append(row)
+    return result
+
+
+def _build_converted_stats(
+    db_rows: list[Row],
+    table_duration_seconds: float,
+    start_ts_idx: int,
+    mean_idx: int | None,
+    min_idx: int | None,
+    max_idx: int | None,
+    last_reset_ts_idx: int | None,
+    state_idx: int | None,
+    sum_idx: int | None,
+    convert: Callable[[float | None], float | None] | Callable[[float], float],
+) -> list[StatisticsRow]:
+    """Build a list of statistics with unit conversion."""
+    result: list[StatisticsRow] = []
+    ent_results_append = result.append
+    for db_row in db_rows:
+        row: StatisticsRow = {
+            "start": (start_ts := db_row[start_ts_idx]),
+            "end": start_ts + table_duration_seconds,
+        }
+        if last_reset_ts_idx is not None:
+            row["last_reset"] = db_row[last_reset_ts_idx]
+        if mean_idx is not None:
+            row["mean"] = None if (v := db_row[mean_idx]) is None else convert(v)
+        if min_idx is not None:
+            row["min"] = None if (v := db_row[min_idx]) is None else convert(v)
+        if max_idx is not None:
+            row["max"] = None if (v := db_row[max_idx]) is None else convert(v)
+        if state_idx is not None:
+            row["state"] = None if (v := db_row[state_idx]) is None else convert(v)
+        if sum_idx is not None:
+            row["sum"] = None if (v := db_row[sum_idx]) is None else convert(v)
+        ent_results_append(row)
+    return result
+
+
+def _sorted_statistics_to_dict(
     hass: HomeAssistant,
-    session: Session,
     stats: Sequence[Row[Any]],
     statistic_ids: set[str] | None,
     _metadata: dict[str, tuple[int, StatisticMetaData]],
     convert_units: bool,
     table: type[StatisticsBase],
-    start_time: datetime | None,
     units: dict[str, str] | None,
     types: set[Literal["last_reset", "max", "mean", "min", "state", "sum"]],
 ) -> dict[str, list[StatisticsRow]]:
@@ -2120,19 +2194,23 @@ def _sorted_statistics_to_dict(  # noqa: C901
     state_idx = field_map["state"] if "state" in types else None
     sum_idx = field_map["sum"] if "sum" in types else None
     sum_only = len(types) == 1 and sum_idx is not None
+    row_idxes = (mean_idx, min_idx, max_idx, last_reset_ts_idx, state_idx, sum_idx)
     # Append all statistic entries, and optionally do unit conversion
     table_duration_seconds = table.duration.total_seconds()
-    for meta_id, stats_list in stats_by_meta_id.items():
+    for meta_id, db_rows in stats_by_meta_id.items():
         metadata_by_id = metadata[meta_id]
         statistic_id = metadata_by_id["statistic_id"]
         if convert_units:
             state_unit = unit = metadata_by_id["unit_of_measurement"]
             if state := hass.states.get(statistic_id):
                 state_unit = state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
-            convert = _get_statistic_to_display_unit_converter(unit, state_unit, units)
+            convert = _get_statistic_to_display_unit_converter(
+                unit, state_unit, units, allow_none=False
+            )
         else:
             convert = None
 
+        build_args = (db_rows, table_duration_seconds, start_ts_idx)
         if sum_only:
             # This function is extremely flexible and can handle all types of
             # statistics, but in practice we only ever use a few combinations.
@@ -2140,53 +2218,16 @@ def _sorted_statistics_to_dict(  # noqa: C901
             # For energy, we only need sum statistics, so we can optimize
             # this path to avoid the overhead of the more generic function.
             assert sum_idx is not None
-            result[statistic_id] = _fast_build_sum_list(
-                stats_list,
-                table_duration_seconds,
-                convert,
-                start_ts_idx,
-                sum_idx,
-            )
-            continue
-
-        ent_results_append = result[statistic_id].append
-        #
-        # The below loop is a red hot path for energy, and every
-        # optimization counts in here.
-        #
-        # Specifically, we want to avoid function calls,
-        # attribute lookups, and dict lookups as much as possible.
-        #
-        for db_state in stats_list:
-            row: StatisticsRow = {
-                "start": (start_ts := db_state[start_ts_idx]),
-                "end": start_ts + table_duration_seconds,
-            }
-            if last_reset_ts_idx is not None:
-                row["last_reset"] = db_state[last_reset_ts_idx]
             if convert:
-                if mean_idx is not None:
-                    row["mean"] = convert(db_state[mean_idx])
-                if min_idx is not None:
-                    row["min"] = convert(db_state[min_idx])
-                if max_idx is not None:
-                    row["max"] = convert(db_state[max_idx])
-                if state_idx is not None:
-                    row["state"] = convert(db_state[state_idx])
-                if sum_idx is not None:
-                    row["sum"] = convert(db_state[sum_idx])
+                _stats = _build_sum_converted_stats(*build_args, sum_idx, convert)
             else:
-                if mean_idx is not None:
-                    row["mean"] = db_state[mean_idx]
-                if min_idx is not None:
-                    row["min"] = db_state[min_idx]
-                if max_idx is not None:
-                    row["max"] = db_state[max_idx]
-                if state_idx is not None:
-                    row["state"] = db_state[state_idx]
-                if sum_idx is not None:
-                    row["sum"] = db_state[sum_idx]
-            ent_results_append(row)
+                _stats = _build_sum_stats(*build_args, sum_idx)
+        elif convert:
+            _stats = _build_converted_stats(*build_args, *row_idxes, convert)
+        else:
+            _stats = _build_stats(*build_args, *row_idxes)
+
+        result[statistic_id] = _stats
 
     return result