sqlalchemy func.group_concat и случайный порядок данных - PullRequest
0 голосов
/ 02 октября 2019

У меня следующий запрос, который использует func.group_concat для группировки некоторых данных

r  = aliased(Rank)
t  = aliased(Team)
p  = aliased(Participant)
players_ranks_data = (
    db.session.query(
        p,
        r.id.label('player_team_skill_id'),
        r.name.label('player_team_skill_name'),
        func.group_concat(t.name),
    )
    .outerjoin(r, r.id == p.team_skill)
    .outerjoin(t, t.id == p.team_id)
    .filter(p.event_id == event_data.id)
    .filter(p.team_id != '')
    .group_by('player_team_skill_name')
    .all()
)

Когда я печатаю то, что было получено

print('players_ranks_data: {}'.format(players_ranks_data))

Я вижу полные данные, ноделать это несколько раз дает мне другой порядок возвращаемых данных. Например: 1-е выполнение

players_ranks_data: [(<Participant 104>, 4, u'advanced', u'text1,item1,other thingy,something else,what is that')]

2-е выполнение

players_ranks_data: [(<Participant 104>, 4, u'advanced', u'what is that, item1,other thingy, text1, something else')]

Это действительно странно, потому что когда я выполняю этот запрос непосредственно в БД (MySQL), я не всегда получаю один и тот же порядокэлементы в результате тоже.

SELECT
  `Rank_1`.id AS player_team_skill_id,
  `Rank_1`.name AS player_team_skill_name,
  GROUP_CONCAT(`Team_1`.name) AS group_concat_1
FROM
  `Participant` AS `Participant_1`
  LEFT OUTER JOIN `Rank` AS `Rank_1`
    ON `Rank_1`.id = `Participant_1`.team_skill
  LEFT OUTER JOIN `Team` AS `Team_1`
    ON `Team_1`.id = `Participant_1`.team_id
WHERE `Participant_1`.event_id = 2
  AND `Participant_1`.team_id != ''
GROUP BY player_team_skill_name;

Чего-то не хватает в моем исходном запросе sqlalchemy или в конфигурации MySQL?

EDIT 1 : на самом деле, я снова провел несколько тестови похоже, что результаты в MySQL (5.7) тоже не упорядочены. Что здесь происходит?

1 Ответ

1 голос
/ 02 октября 2019

Результаты SQL являются (множественными) наборами и, как таковые, не имеют порядка, если вы явно не определите его. Это относится и к групповым строкам, создаваемым GROUP BY;в группах нет порядка, и поэтому агрегаты получают значения в любом порядке, в котором происходит текущий запрос в зависимости от плана, физической схемы, расписания и т. д. Решение состоит в том, чтобы явно определить порядок :

func.group_concat(t.name.op("ORDER BY")(t.name))

. При этом используется универсальная операторная функция для создания необходимого синтаксиса SQL. SQLAlchemy предоставляет помощник aggregate_order_by для того же синтаксиса, но он предоставляется только для диалекта Postgresql.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...