我不明白为什么我的查询不按我指定的列对计数结果进行分组。相反,它会计算“ un”子表中所有result_id的出现。
我在那里想念什么?
示例数据库的完整结构和我尝试过的查询都在这里:
https://www.db-fiddle.com/f/4HuLpTFWaE2yBSQSzf3dX4/4
CREATE TABLE combination (
combination_id integer,
ticket_id integer,
outcomes integer[]
);
CREATE TABLE outcome (
outcome_id integer,
ticket_id integer,
val double precision
);
insert into combination
values
(510,188,'{52,70,10}'),
(511,188,'{52,56,70,18,10}'),
(512,188,'{55,70,18,10}'),
(513,188,'{54,71,18,10}'),
(514,189,'{52,54,71,18,10}'),
(515,189,'{55,71,18,10,54,56}')
;
insert into outcome
values
(52,188,1.3),
(70,188,2.1),
(18,188,2.6),
(56,188,2),
(55,188,1.1),
(54,188,2.2),
(71,188,3),
(10,188,0.5),
(54,189,2.2),
(71,189,3),
(18,189,2.6),
(55,189,2)
with un AS (
SELECT combination_id, unnest(outcomes) outcome
FROM combination c JOIN
outcome o
on o.ticket_id = c.ticket_id
GROUP BY 1,2
)
SELECT combination_id, cnt
FROM (SELECT un.combination_id,
COUNT(CASE WHEN o.val >= 1.3 THEN 1 END) as cnt
FROM un JOIN
outcome o
on o.outcome_id = un.outcome
GROUP BY 1
) x
GROUP BY 1, 2
ORDER BY 1
预期结果应该是:
510 2
511 4
512 2
513 3
514 4
515 4
答案 0 :(得分:1)
假设,您具有以下PK约束:
tcourses: async (user, args, { models }) => {
return await models.TCourses.findAll({
where: { UserId: user.id },
include: [{model: models.Course, as: 'Course', include: [{model: models.Category, as: 'Category'}]}]
})
},
和假设此目标:
对于表
CREATE TABLE combination (
combination_id integer PRIMARY KEY
, ticket_id integer
, outcomes integer[]
);
CREATE TABLE outcome (
outcome_id integer
, ticket_id integer
, val double precision
, PRIMARY KEY (ticket_id, outcome_id)
);
中的每一行,计算combination
中至少有一行匹配outcomes
和{{表outcome_id
-和ticket_id
中的1}}。
假设高于PK,这将简化为一个更简单的查询:
outcome
有了索引支持,这种替代方法可能会更快:
val >= 1.3
此外,它不需要SELECT c.combination_id, count(*) AS cnt
FROM combination c
JOIN outcome o USING (ticket_id)
WHERE o.outcome_id = ANY (c.outcomes)
AND o.val >= 1.3
GROUP BY 1
ORDER BY 1;
上的PK。由于SELECT c.combination_id, count(*) AS cnt
FROM combination c
CROSS JOIN LATERAL unnest(c.outcomes) AS u(outcome_id)
WHERE EXISTS (
SELECT
FROM outcome o
WHERE o.outcome_id = u.outcome_id
AND o.val >= 1.3
AND o.ticket_id = c.ticket_id -- ??
)
GROUP BY 1
ORDER BY 1;
,任何数量的匹配行仍计为 1 。
db <>提琴here
一如既往,最佳答案取决于对设置和要求的精确定义。
答案 1 :(得分:1)
@forpas答案的简单版本:
-您不需要在“ with”语句中加入结果。
with un AS (
SELECT combination_id, ticket_id, unnest(outcomes) outcome
FROM combination c
-- no need to join to outcomes here
GROUP BY 1,2,3
)
SELECT combination_id, cnt FROM
(
SELECT un.combination_id,
COUNT(CASE WHEN o.val >= 1.3 THEN 1 END) as cnt
FROM un
JOIN outcome o on o.outcome_id = un.outcome
and o.ticket_id = un.ticket_id
GROUP BY 1
)x
GROUP BY 1,2
ORDER BY 1
正如其他人指出的那样,根据您的输入数据,514的预期结果应该为3。
我还想建议,在group by和order by子句中使用完整的字段名可以使查询更易于调试和维护。
答案 2 :(得分:0)
您还需要加入ticket_id
:
with un AS (
SELECT c.combination_id, c.ticket_id, unnest(c.outcomes) outcome
FROM combination c JOIN outcome o
on o.ticket_id = c.ticket_id
GROUP BY 1,2,3
)
SELECT combination_id, cnt
FROM (SELECT un.combination_id, un.ticket_id,
COUNT(CASE WHEN o.val >= 1.3 THEN 1 END) as cnt
FROM un JOIN outcome o
on o.outcome_id = un.outcome and o.ticket_id = un.ticket_id
GROUP BY 1,2
) x
GROUP BY 1, 2
ORDER BY 1
请参见demo。
结果:
> combination_id | cnt
> -------------: | --:
> 510 | 2
> 511 | 4
> 512 | 2
> 513 | 3
> 514 | 3
> 515 | 4