【问题标题】:stuck with the sql / hql query group by坚持使用 sql / hql 查询组
【发布时间】:2012-11-08 17:53:18
【问题描述】:
id          device_id   config_status   update_finished
1           5015001     SUCCESS     11-OCT-2012
2           5015001     SUCCESS     23-OCT-2012
3           5015001     PENDING     23-OCT-2012
4           5015001     PENDING     23-OCT-2012
5           5016222     PENDING     12-OCT-2012
6           5016222     PENDING     22-OCT-2012

嗨,上面是我的表格,上面有一些示例数据。我想要实现的是为每个 device_id 获取最后的 SUCCESS 状态(日期在 update_finished 字段中)和所有 PENDING 状态。从上面的示例中,结果查询应该有:

id          device_id   config_status   update_finished
2           5015001     SUCCESS     23-OCT-2012
3           5015001     PENDING     23-OCT-2012
4           5015001     PENDING     23-OCT-2012
5           5016222     PENDING     12-OCT-2012
6           5016222     PENDING     22-OCT-2012

这意味着只有按日期列 update_finished 的最后一个 SUCCESS 状态以及每个 device_id 的所有 PENDING 状态。

目前我正在尝试使用 GROUP BY:SELECT device_id, config_status, max(update_finished) AS "LastUpdate" from config_status WHERE config_status = 'SUCCESS' group by device_id, config_status

这确实只返回每个 device_id 的最后一个 SUCCESS 状态,但它错过了 PENDING 状态并且它没有 id 列。如果我将 id 字段添加到 GROUP BY 中,那么无论如何分组将是 id

谁能帮我正确查询?它也应该有子查询吗?最后我需要将它作为HQL,但我认为它会与SQL非常相似。

编辑:

感谢大家帮助我。所有这些查询都有效,但最适合我@Remigio 提供的查询,因为将其转换为返回参数化对象的 HQL 查询是最简单的,而不仅仅是对象。

这是我在初始示例中省略的附加字段的工作 HQL 查询

List<ConfigStatus> statuses = getHibernateTemplate().find("select c from ConfigStatus c " +
                "where (configStatus = 'SUCCESS' and updateFinished = (select max(updateFinished) from " +
                "ConfigStatus c1 where c1.device.deviceId = c.device.deviceId and c1.configStatus = 'SUCCESS' and c1.configFile.configFileId = ?)) " +
                "or configStatus = 'PENDING' and configFile.configFileId = ?", new Object[] {configFileId, configFileId});

【问题讨论】:

  • 了解oracle版本对于利用过分区分析功能很重要。
  • @danihp 你好,Oracle 数据库版本是 10.2
  • 很好,我已经引用了 oracle 文档示例和一个版本供您查询。请参阅我的(未经测试的)答案。
  • @danihp 对不起,我的数据库版本错了,实际上是 11

标签: java sql oracle hql


【解决方案1】:

你可以试试这个查询:

select * from device d
where (config_status='SUCCESS' and update_finished = (select max(update_finished) from
device d1 where d1.device_id = d.device_id and d1.config_status='SUCCESS'))
or config_status='PENDING'

【讨论】:

  • 太棒了!这最适合我可以轻松地将其转换为 HQL 的原因。我用答案编辑我的帖子
【解决方案2】:

基于oracle sample:

SELECT last_name FROM 
   (SELECT last_name, ROW_NUMBER() OVER (ORDER BY last_name) R FROM employees)
   WHERE R BETWEEN 51 and 100;

您的查询应该是:

select * from (
  SELECT device_id, config_status, update_finished AS "LastUpdate" ,
  ROW_NUMBER() OVER (ORDER BY update_finished desc) R
  from config_status WHERE config_status = 'SUCCESS' 
) where R = 1

已编辑

select device_id, config_status, update_finished
from (
  SELECT device_id, config_status, update_finished  ,
  ROW_NUMBER() OVER (ORDER BY update_finished desc) R
  from config_status WHERE config_status = 'SUCCESS' 
) where R = 1
union all
SELECT device_id, config_status, update_finished  
from config_status WHERE config_status = 'PENDING' 

【讨论】:

  • 嗨,对不起,我第一次弄错了数据库版本。它实际上是第 11 版。您上面的查询返回:device_id: 5015000status:SUCCESSlast_update: 24-OCT-12R: 1 不是我所期望的。我现在也看看这个例子
  • 5015000 不在您的示例数据中。我只写了查询的难部分,你应该将它与所有其他行联合起来。查看已编辑的查询。
【解决方案3】:
- 尝试这个: 与 T_CONFIG_STATUS 作为 ( 从 DUAL union 中选择 1 作为 id,5015001 作为 DEVICE_ID,'SUCCESS' 作为 CONFIG_STATUS,TO_DATE('11-OCT-2012','DD-MON-YYYY') 作为 update_finished 从 DUAL 联合中选择 2, 5015001, 'SUCCESS', TO_DATE('23-OCT-2012','DD-MON-YYYY') 从 DUAL 联合中选择 3, 5015001, 'PENDING', TO_DATE('23-OCT-2012','DD-MON-YYYY') 从双重联合中选择 4, 5015001, 'PENDING', TO_DATE('23-OCT-2012','DD-MON-YYYY') 从双重联合中选择 5, 5016222, 'PENDING', TO_DATE('12-OCT-2012','DD-MON-YYYY') 从 DUAL 中选择 6, 5016222, 'PENDING', TO_DATE('22-OCT-2012','DD-MON-YYYY') ) , q1 为 ( 选择 id、DEVICE_ID、CONFIG_STATUS、UPDATE_FINISHED、 max(UPDATE_FINISHED) over(partition by DEVICE_ID, CONFIG_STATUS) as MAX_UPDATE_FINISHED 从 T_CONFIG_STATUS ) , q2 为 ( 选择 id、device_id、config_status、update_finished、max_update_finished、 案子 当 config_status='SUCCESS' 和 update_finished=max_update_finished 然后 'keep' 当 config_status='PENDING' 然后 'keep' 否则“丢弃” 以 KEEP_RECORD 结尾 从第一季度开始 ) 选择 id、device_id、config_status、update_finished 从第二季度开始,其中 KEEP_RECORD='keep' 按 ID 排序;

因此,表 t_config_status 只不过是一个包含 Skyzer 问题中的样本数据的虚拟表。

然后查询 q1 获取具有相同 device_id 和 cojnfig_status 的所有记录集中的每条记录的最大更新日期。

查询 q2 然后计算另一个标志来决定是保留还是丢弃记录。因此,它保留每条具有 PE​​NDINGstatus 的记录。但它只保留那些具有最新更新完成日期的 SUCCESS 状态的记录。

最后的查询然后只是使用过滤器来呈现标志值为'keep'的记录,并忽略那些标志值为'discard'的记录。

希望这能澄清逻辑。

【讨论】:

    猜你喜欢
    • 2022-12-17
    • 2020-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-15
    • 2018-10-11
    • 2016-09-22
    相关资源
    最近更新 更多