Sql 计算给定时间段内第一个和最后一个条目相等的数量

Sql 计算给定时间段内第一个和最后一个条目相等的数量,sql,database,hibernate,postgresql,hql,Sql,Database,Hibernate,Postgresql,Hql,给定这样一个表: id | news_id(fkey)| status | date 1 10 PUBLISHED 2016-01-10 2 20 UNPUBLISHED 2016-01-10 3 10 UNPUBLISHED 2016-01-12 4 10 PUBLISHED 2016-01-1

给定这样一个表:

id   | news_id(fkey)|    status      |    date
1          10          PUBLISHED      2016-01-10
2          20          UNPUBLISHED    2016-01-10
3          10          UNPUBLISHED    2016-01-12
4          10          PUBLISHED      2016-01-15
5          10          UNPUBLISHED    2016-01-16
6          20          PUBLISHED      2016-01-18
7          10          PUBLISHED      2016-01-18
8          20          UNPUBLISHED    2016-01-20
9          30          PUBLISHED      2016-01-20
10         30          UNPUBLISHED    2016-01-21
我想计算在给定时间段内,第一个和最后一个状态相等,并且状态也等于查询中给定的不同新闻

因此,对于2016-01-01至2016-02-01的表格查询,将返回:

1其中状态为“已发布”,因为新闻id 10已在2016-01-10第一行和2016-01-18最后一行发布 1,其中状态为“未发布”,因为新闻id 20在第一行和最后一行都未发布 请注意,news_id=30没有出现在结果中,因为他的第一个/最后一个状态是相反的

我使用以下查询完成了此操作:

SELECT count(*) FROM
(
    SELECT DISTINCT ON (news_id)
    news_id, status as first_status
    FROM news_events
    where date >= '2015-11-12 15:01:56.195'
    ORDER BY news_id, date
) first
JOIN (
    SELECT DISTINCT ON (news_id)
    news_id, status as last_status
    FROM news_events
    where date >= '2015-11-12 15:01:56.195'
    ORDER BY news_id, date DESC

) last
using (news_id)
where first_status = last_status
and first_status = 'PUBLISHED'
现在,我必须将查询转换为SQL我们的内部Java框架,不幸的是,它不支持子查询,除非使用EXISTS或not EXISTS。有人告诉我,如果可能,可以使用EXISTS子句将查询转换为EXISTS子句,或者尝试寻找其他解决方案。然而,我却一无所知。有人能帮我吗


编辑:正如我现在被告知的那样,问题不在于我们的框架,而在于Hibernate——如果我理解正确,您就不能在HQL中加入内部select,因为这更像是一种解决方法,所以不确定这是否正确地解决了您的问题。但考虑到以下几点:

新闻必须先发布,然后才能取消发布。所以,如果你为每一个已发布的内容加1,为每一个未发布的内容减1,那么你的余额将是正的,或者如果第一个和最后一个都已发布,则准确地说是1。如果未发布的数量与已发布的数量相同,则为0;如果未发布的数量大于已发布的数量,则为负,这在逻辑上是不可能的,但显然可能会出现,因为您在查询中设置了一个日期阈值,在此之前可能会出现“已发布”

您可以使用此查询来查找:

SELECT SUM(CASE status WHEN 'PUBLISHED' THEN 1 ELSE -1 END) AS 'publishbalance'
FROM news_events
WHERE date >= '2015-11-12 15:01:56.195'
GROUP BY news_id

首先,子查询是SQL的重要组成部分。禁止使用它们的框架是一个糟糕的框架

但是,first和last可以用NOT EXISTS表示:其中NOT EXISTS是相同新闻id和日期范围的较早或较晚条目

select count(*)
from mytable first
join mytable last on last.news_id = first.news_id
where date between @from and @to
and not exists
(
  select *
  from mytable before_first
  where before_first.news_id = first.news_id
  and before_first.date < first.date
  and before_first.date >= @from
)
and not exists
(
  select *
  from mytable after_last
  where after_last.news_id = last.news_id
  and after_last.date > last.date
  and after_last.date <= @to
)
and first.status = @status
and last.status = @status;

不存在以进行救援:

SELECT ff.id ,ff.news_id ,ff.status , ff.zdate AS startdate
        , ll.zdate AS enddate
FROM newsflash ff
JOIN newsflash ll
        ON ff.news_id = ll.news_id
        AND ff.status = ll.status
        AND ff.zdate < ll.zdate
        AND  NOT EXISTS (
                SELECT * FROM newsflash nx
                WHERE nx.news_id = ff.news_id
                AND nx.zdate >= '2016-01-01' AND nx.zdate < '2016-02-01'
                AND (nx.zdate < ff.zdate OR nx.zdate > ll.zdate)
                )
ORDER BY ff.id
        ;

没有子查询很难做到这一点。可能,但有挑战性。数据库的接口应该是固定的,这样你就可以充分利用SQL的功能。需要更多的解释。@蒙蒂,你想让我解释什么?只要告诉我你想从你在问题中发布的表结构中得到什么输出。使用模糊层的乐趣。。。你不能仅仅使用一个本地查询来克服HQL的限制吗?这是一个很好的想法。这当然值得考虑。这是一个非常聪明的解决方法,谢谢,尽管在应用程序的另一部分中,我必须选择所有不同的新闻id,而不是计数。在你的查询中可能吗?有点:考虑到这些值是严格交替的,第一个值和最后一个值将与非零余额相等,但与零余额不同。确切地说,人们将查找具有countstatus=@status>countstatus的新闻≠@地位我看到的唯一问题是:在我们发现这样的消息后,我们将不得不统计它们。两个步骤,我们通常在子查询中执行第一步:-据我所知,这是一个hibernate/hql问题。这解决了问题,尽管我重新创建了类似以下内容的开头:选择COUNT*from mytable first,mytable last where last.news\u id=first.news\u id。非常感谢!是的,也是这样。mytable first、mytable last是mytable first交叉连接mytable last的1992年以前的语法。过滤器将完全转到where子句,正确。这样或那样,这个查询比需要的复杂得多,但这是由于HQL限制,而不是我们的错误:-注意:@在postgres中不存在。在sql92和IMHO中都没有