同一select/where查询中的sql(oracle)计数和总和

同一select/where查询中的sql(oracle)计数和总和,sql,oracle,select,count,where,Sql,Oracle,Select,Count,Where,关于以下正确回答的问题: 给定下表,在oracle sql数据库中进行测试: +--+---+----+---+ |id |名称|开始|停止| +--+---+----+---+ |1 | A | 1 | 5| +--+---+----+---+ |2 | A | 2 | 6| +--+---+----+---+ |3 | A | 5 | 8| +--+---+----+---+ |4 | A | 9 | 10| +--+---+----+---+ |5 | B | 3 | 6| +--+--

关于以下正确回答的问题:

给定下表,在oracle sql数据库中进行测试:

+--+---+----+---+ |id |名称|开始|停止| +--+---+----+---+ |1 | A | 1 | 5| +--+---+----+---+ |2 | A | 2 | 6| +--+---+----+---+ |3 | A | 5 | 8| +--+---+----+---+ |4 | A | 9 | 10| +--+---+----+---+ |5 | B | 3 | 6| +--+---+----+---+ |6 | B | 4 | 8| +--+---+----+---+ |7 | B | 1 | 2| +--+---+----+---+ 现在,我想找出包含[start,stop]n_重叠的重叠间隔端点的数量,以及具有相同名称的所有id的停止值的总和,即:

+--+---+----+---+------+------+ |id | name | start | stop | n |重叠| sum |停止| +--+---+----+---+------+------+ |1 | A | 1 | 5 | 3 | 19| +--+---+----+---+------+------+ |2 | A | 2 | 6 | 3 | 19| +--+---+----+---+------+------+ |3 | A | 4 | 8 | 3 | 19| +--+---+----+---+------+------+ |4 | A | 9 | 10 | 1 | 10| +--+---+----+---+------+------+ |5 | B | 3 | 6 | 2 | 14| +--+---+----+---+------+------+ |6 | B | 4 | 8 | 2 | 14| +--+---+----+---+------+------+ |7 | B | 1 | 2 | 1 | 2| +--+---+----+---+------+------+ 我尝试了这个解决方案,效果很好:

select t.*,
   (select count(*)
    from test t2
    where t2.name = t.name and
          t2.start <= t.stop and
          t2.stop >= t.start
   ) as n_overlap,
   (select sum(stop)
    from test t2
    where t2.name = t.name and
          t2.start <= t.stop and
          t2.stop >= t.start
   ) as sum_stops 
from test t;
但是,是否有办法压缩两个select/where查询,例如:

select t.*,
   (select count(*) as n_overlap, sum(stop) as sum_stops
    from test t2
    where t2.name = t.name and
          t2.start <= t.stop and
          t2.stop >= t.start
   ) 
from test t;

这会导致值过多错误?

您应该能够通过以下方式使用连接和组执行所需操作:


您应该能够通过以下方式使用连接和组执行您想要的操作:

这应该做到:

SELECT test.*, n_overlap, sum_stops
FROM test
LEFT JOIN (
    SELECT m.id, COUNT(o.id) AS n_overlap, SUM(o.stop) AS sum_stops
    FROM test AS m
    INNER JOIN test AS o ON
        /* m.id <> o.id AND */
        m.name = o.name AND
        m.stop >= o.start AND
        o.stop >= m.start
    GROUP BY m.id
) AS sq ON test.id = sq.id
我可以补充一点,您的预期输出考虑任何给定的行与其自身重叠,请参见第4行。您可能希望排除与自身匹配的行。

这应该可以做到:

SELECT test.*, n_overlap, sum_stops
FROM test
LEFT JOIN (
    SELECT m.id, COUNT(o.id) AS n_overlap, SUM(o.stop) AS sum_stops
    FROM test AS m
    INNER JOIN test AS o ON
        /* m.id <> o.id AND */
        m.name = o.name AND
        m.stop >= o.start AND
        o.stop >= m.start
    GROUP BY m.id
) AS sq ON test.id = sq.id

我可以补充一点,您的预期输出考虑任何给定的行与其自身重叠,请参见第4行。您可能希望排除与自身匹配的行。

谢谢@Nick。它给出的错误不是GROUP BY表达式,但如果我从SELECTORY中删除t.*,它就会工作,SELECTORY用于MySQL的lax GROUP BY规则。如果您需要除id以外的所有t.*值,您应该能够将它们全部放入组中,例如按t.id、t.name、t.start、t.stopthank@Nick分组。如果我显式列出SELECT和GROUP BY中的所有列/值,它就会工作,但如果我简单地使用SELECT t.*,COUNTt2.name作为。。。和按t.*分组,当有许多列/值时,这可能是一个问题。@Marco我编辑了我的答案以反映这一点。正如您所说,当有许多列和值时,这是一种痛苦。解决这个问题的唯一方法是使用Salman在回答中提出的子查询。你可能想接受这一点。谢谢@Nick。它给出的错误不是GROUP BY表达式,但如果我从SELECTORY中删除t.*,它就会工作,SELECTORY用于MySQL的lax GROUP BY规则。如果您需要除id以外的所有t.*值,您应该能够将它们全部放入组中,例如按t.id、t.name、t.start、t.stopthank@Nick分组。如果我显式列出SELECT和GROUP BY中的所有列/值,它就会工作,但如果我简单地使用SELECT t.*,COUNTt2.name作为。。。和按t.*分组,当有许多列/值时,这可能是一个问题。@Marco我编辑了我的答案以反映这一点。正如您所说,当有许多列和值时,这是一种痛苦。解决这个问题的唯一方法是使用Salman在回答中提出的子查询。你可能想接受这一点。
SELECT test.*, n_overlap, sum_stops
FROM test
LEFT JOIN (
    SELECT m.id, COUNT(o.id) AS n_overlap, SUM(o.stop) AS sum_stops
    FROM test AS m
    INNER JOIN test AS o ON
        /* m.id <> o.id AND */
        m.name = o.name AND
        m.stop >= o.start AND
        o.stop >= m.start
    GROUP BY m.id
) AS sq ON test.id = sq.id