Нет, похоже, что вы делаете это неправильно. Соединения MongoDB являются «клиентской стороной». Очень похоже на то, что вы сказали:
На данный момент я получаю комментарии, соответствующие моим критериям, затем выясняя все uid в этом наборе результатов, получая пользовательские объекты и объединяя их с комментариями. Похоже, я делаю это неправильно.
blockquote>1) Select from the collection you're interested in. 2) From that collection pull out ID's you need 3) Select from other collections 4) Decorate your original results.
Это не «реальное» соединение, но на самом деле оно намного полезнее, чем соединение SQL, потому что вам не нужно иметь дело с дубликатом строки для «многих» сторонних объединений, вместо этого вы украшаете первоначально выбранный набор.
На этой странице много глупостей и FUD. Оказывается, 5 лет спустя MongoDB все еще есть.
Одним из решений было бы выполнение всей операции за одно сканирование таблицы (без объединений или подзапросов), используя условное агрегирование :
SELECT
box_score.team_name,
ROUND(AVG(CASE WHEN team_name = 'Miami Heat' AND WIN_LOSS = 'W' THEN eFG END),3) Heat_eFG,
ROUND(AVG(CASE WHEN team_name = 'New York Knicks' AND WIN_LOSS = 'L' THEN eFG END),3) Knicks_eFG,
ROUND(AVG(CASE WHEN team_name = 'Miami Heat' AND WIN_LOSS = 'W' THEN OPP_eFG END),3) Heat_OPP_eFG,
ROUND(AVG(CASE WHEN team_name = 'New York Knicks' AND WIN_LOSS = 'L' THEN OPP_eFG END),3) Knicks_OPP_eFG,
ROUND(AVG(CASE WHEN team_name = 'Miami Heat' AND WIN_LOSS = 'W' THEN TOV_PCT END),3) Heat_TOV_PCT,
ROUND(AVG(CASE WHEN team_name = 'New York Knicks' AND WIN_LOSS = 'L' THEN TOV_PCT END),3) Knicks_TOV_PCT,
ROUND(AVG(CASE WHEN team_name = 'Miami Heat' AND WIN_LOSS = 'W' THEN OPP_TOV_PCT END),3) Heat_OPP_TOV_PCT,
ROUND(AVG(CASE WHEN team_name = 'New York Knicks' AND WIN_LOSS = 'L' THEN OPP_TOV_PCT END),3) Knicks_OPP_TOV_PCT,
ROUND(AVG(CASE WHEN team_name = 'Miami Heat' AND WIN_LOSS = 'W' THEN ORB_PCT END),3) Heat_ORB_PCT,
ROUND(AVG(CASE WHEN team_name = 'New York Knicks' AND WIN_LOSS = 'L' THEN ORB_PCT END),3) Knicks_ORB_PCT,
ROUND(AVG(CASE WHEN team_name = 'Miami Heat' AND WIN_LOSS = 'W' THEN DRB_PCT END),3) Heat_DRB_PCT,
ROUND(AVG(CASE WHEN team_name = 'New York Knicks' AND WIN_LOSS = 'L' THEN DRB_PCT END),3) Knicks_DRB_PCT,
ROUND(AVG(CASE WHEN team_name = 'Miami Heat' AND WIN_LOSS = 'W' THEN FTA_RATE END),3) Heat_FTA_RATE,
ROUND(AVG(CASE WHEN team_name = 'New York Knicks' AND WIN_LOSS = 'L' THEN FTA_RATE END),3) Knicks_FTA_RATE,
ROUND(AVG(CASE WHEN team_name = 'Miami Heat' AND WIN_LOSS = 'W' THEN OPP_FTA_RATE END),3) Heat_OPP_FTA_RATE,
ROUND(AVG(CASE WHEN team_name = 'New York Knicks' AND WIN_LOSS = 'L' THEN OPP_FTA_RATE END),3) Knicks_OPP_FTA_RATE
FROM box_score
WHERE team_name IN ('Miami Heat', 'New York Knicks') AND game_date < '2019-03-07'
Вот еще одна версия запроса, если вы хотите вычислить среднее значение, например, как eFG
для побед в Майами И OPP_eFG
для потерь в Нью-Йорке в одном столбце. Это все еще зависит от условной агрегации. Я также немного упростил логику, перенеся условия в предложение WHERE
.
SELECT
box_score.team_name,
ROUND(AVG(CASE
WHEN team_name = 'Miami Heat' THEN eFG
WHEN team_name = 'New York Knicks' THEN OPP_eFG
END, 3) Heats_eFG_Knicks_OPP_eFG,
ROUND(AVG(CASE
WHEN team_name = 'Miami Heat' THEN OPP_eFG
WHEN team_name = 'New York Knicks' THEN eFG
END, 3) Heats_OPP_eFG_Knicks_eFG,
ROUND(AVG(CASE
WHEN team_name = 'Miami Heat' THEN TOV_PCT
WHEN team_name = 'New York Knicks' THEN OPP_TOV_PCT
END, 3) Heats_TOV_PCT_Knicks_OPP_TOV_PCT,
ROUND(AVG(CASE
WHEN team_name = 'Miami Heat' THEN OPP_TOV_PCT
WHEN team_name = 'New York Knicks' THEN TOV_PCT
END, 3) Heats_OPP_TOV_PCT_Knicks_TOV_PCT,
ROUND(AVG(CASE
WHEN team_name = 'Miami Heat' THEN FTA_RATE
WHEN team_name = 'New York Knicks' THEN OPP_FTA_RATE
END, 3) Heats_FTA_RATE_Knicks_OPP_FTA_RATE,
ROUND(AVG(CASE
WHEN team_name = 'Miami Heat' THEN OPP_FTA_RATE
WHEN team_name = 'New York Knicks' THEN FTA_RATE
END, 3) Heats_OPP_FTA_RATE_Knicks_FTA_RATE
FROM box_score
WHERE
game_date < '2019-03-07'
AND (
( team_name = 'Miami Heat' AND win_loss = 'W' )
OR ( team_name = 'New York Knicks' AND win_loss = 'L')
)
Примечание: как прокомментировал wildpasser , вы, вероятно, хотите использовать одинарные кавычки вместо двойных кавычек вокруг литеральных значений (это стандарт SQL). Я глобально все двойные кавычки в исходном запросе в одинарные кавычки.
Я хотел бы продвигать Common Table Expressions для этого:
WITH selector_heat as (
SELECT
box_score.team_name,
ROUND(AVG(eFG),3) eFG,
ROUND(AVG(OPP_eFG),3) OPP_eFG,
ROUND(AVG(TOV_PCT),3) TOV_PCT,
ROUND(AVG(OPP_TOV_PCT),3) OPP_TOV_PCT,
ROUND(AVG(ORB_PCT),3) ORB_PCT,
ROUND(AVG(DRB_PCT),3) DRB_PCT,
ROUND(AVG(FTA_RATE),3) FTA_RATE,
ROUND(AVG(OPP_FTA_RATE),3) OPP_FTA_RATE
FROM box_score
WHERE team_name = 'Miami Heat' AND WIN_LOSS = 'W' AND game_date < '2019-03-07'
)
, selector_knicks as (
...
)
select H.eFG - K.OPP_eFG as magic_nbr
from selector_heat H
join selector_knicks K ON (1=1)
Подробнее о синтаксисе здесь: https://www.sqlite.org/lang_with.html , но пока игнорируйте «рекурсивные» биты, они вам не нужны этот экземпляр.
В качестве альтернативы (и с немного другим углом подхода) вы можете использовать предложения Window для агрегирования «на команду», а затем использовать результаты. Более подробная информация здесь: https://www.sqlite.org/windowfunctions.html#introduction_to_window_functions
Пример:
SELECT
team_name,
WIN_LOSS,
ROUND(AVG(eFG) OVER (partition by team_name, win_loss),3) as eFG
...
from box_score
where game_date < '2019-03-07'
С этим набором результатов у вас есть свои средние значения для все команды и комбинации win_loss. Оберните это в CTE и присоедините к себе на подходящих условиях, например
WITH cte as (SELECT ...)
SELECT H.eFG - K.OPP_eFG as magic_nbr
FROM cte H join cte K
ON (H.team_name = 'Miami Heat'
AND K.team_name = 'NY Knicks'
AND H.win_loss = 'W'
AND K.win_loss = 'L')
Если вы хотите сначала вычислить средние значения , а затем усреднить их, вы можете использовать два уровня агрегирования:
SELECT ROUND(AVG(eFG), 3) as eFG,
ROUND(AVG(OPP_eFG), 3) as OPP_eFG,
ROUND(AVG(TOV_PCT), 3) as TOV_PCT,
ROUND(AVG(OPP_TOV_PCT), 3) as OPP_TOV_PCT,
ROUND(AVG(ORB_PCT), 3) as ORB_PCT,
ROUND(AVG(DRB_PCT), 3) as DRB_PCT,
ROUND(AVG(FTA_RATE), 3) as FTA_RATE,
ROUND(AVG(OPP_FTA_RATE), 3) as OPP_FTA_RATE
FROM (SELECT bs.team_name,
AVG(eFG) as eFG,
AVG(OPP_eFG) as OPP_eFG,
AVG(TOV_PCT) as TOV_PCT,
AVG(OPP_TOV_PCT) as OPP_TOV_PCT,
AVG(ORB_PCT) as ORB_PCT,
AVG(DRB_PCT) as DRB_PCT,
AVG(FTA_RATE) as FTA_RATE,
AVG(OPP_FTA_RATE) as OPP_FTA_RATE
FROM box_score bs
WHERE game_date < '2019-03-07' AND
( (team_name = 'Miami Heat' AND WIN_LOSS = 'W') OR
(team_name = 'New York Knicks' AND WIN_LOSS = 'L')
)
) bs