diff --git a/homeassistant/components/recorder/history.py b/homeassistant/components/recorder/history.py index 72ae57dde27..0f3db70f66a 100644 --- a/homeassistant/components/recorder/history.py +++ b/homeassistant/components/recorder/history.py @@ -518,48 +518,52 @@ def state_changes_during_period( def _get_last_state_changes_stmt( - schema_version: int, number_of_states: int, entity_id: str | None + schema_version: int, number_of_states: int, entity_id: str ) -> StatementLambdaElement: stmt, join_attributes = lambda_stmt_and_join_attributes( schema_version, False, include_last_changed=False ) if schema_version >= 31: - stmt += lambda q: q.filter( - (States.last_changed_ts == States.last_updated_ts) - | States.last_changed_ts.is_(None) + stmt += lambda q: q.where( + States.state_id + == ( + select(States.state_id) + .filter(States.entity_id == entity_id) + .order_by(States.last_updated_ts.desc()) + .limit(number_of_states) + .subquery() + ).c.state_id ) else: - stmt += lambda q: q.filter( - (States.last_changed == States.last_updated) | States.last_changed.is_(None) + stmt += lambda q: q.where( + States.state_id + == ( + select(States.state_id) + .filter(States.entity_id == entity_id) + .order_by(States.last_updated.desc()) + .limit(number_of_states) + .subquery() + ).c.state_id ) - if entity_id: - stmt += lambda q: q.filter(States.entity_id == entity_id) if join_attributes: stmt += lambda q: q.outerjoin( StateAttributes, States.attributes_id == StateAttributes.attributes_id ) - if schema_version >= 31: - stmt += lambda q: q.order_by( - States.entity_id, States.last_updated_ts.desc() - ).limit(number_of_states) - else: - stmt += lambda q: q.order_by( - States.entity_id, States.last_updated.desc() - ).limit(number_of_states) + + stmt += lambda q: q.order_by(States.state_id.desc()) return stmt def get_last_state_changes( - hass: HomeAssistant, number_of_states: int, entity_id: str | None + hass: HomeAssistant, number_of_states: int, entity_id: str ) -> MutableMapping[str, list[State]]: """Return the last number_of_states.""" - start_time = dt_util.utcnow() - entity_id = entity_id.lower() if entity_id is not None else None - entity_ids = [entity_id] if entity_id is not None else None + entity_id_lower = entity_id.lower() + entity_ids = [entity_id_lower] with session_scope(hass=hass) as session: stmt = _get_last_state_changes_stmt( - _schema_version(hass), number_of_states, entity_id + _schema_version(hass), number_of_states, entity_id_lower ) states = list(execute_stmt_lambda_element(session, stmt)) return cast( @@ -568,7 +572,7 @@ def get_last_state_changes( hass, session, reversed(states), - start_time, + dt_util.utcnow(), entity_ids, include_start_time_state=False, ), diff --git a/tests/components/recorder/test_history.py b/tests/components/recorder/test_history.py index 83d55f978af..670b08f3e21 100644 --- a/tests/components/recorder/test_history.py +++ b/tests/components/recorder/test_history.py @@ -330,7 +330,7 @@ def test_get_last_state_changes(hass_recorder): start = dt_util.utcnow() - timedelta(minutes=2) point = start + timedelta(minutes=1) - point2 = point + timedelta(minutes=1) + point2 = point + timedelta(minutes=1, seconds=1) with patch( "homeassistant.components.recorder.core.dt_util.utcnow", return_value=start diff --git a/tests/components/recorder/test_history_db_schema_30.py b/tests/components/recorder/test_history_db_schema_30.py index 4384f284fe8..ee4bb7ab051 100644 --- a/tests/components/recorder/test_history_db_schema_30.py +++ b/tests/components/recorder/test_history_db_schema_30.py @@ -257,7 +257,7 @@ def test_get_last_state_changes(hass_recorder): start = dt_util.utcnow() - timedelta(minutes=2) point = start + timedelta(minutes=1) - point2 = point + timedelta(minutes=1) + point2 = point + timedelta(minutes=1, seconds=1) with patch( "homeassistant.components.recorder.core.dt_util.utcnow", return_value=start