【问题标题】:Parent-child sql query with order by and limit带有order by和limit的父子sql查询
【发布时间】:2012-11-07 09:20:40
【问题描述】:

我有两个像这样的表格 DOCUMENT 和 ATTRIBUTES

  • DOCUMENT(id),
  • ATTRIBUTE(name, value, doc_fk).

我需要运行一个类似“抽象查询”的查询

select top 100 documents
where $state='COMPLETED'
order by $creationDate

其中$state$creationDate 是两个属性。

请注意,限制是针对文档,而不是属性,并且排序和过滤器针对两个不同的属性。最终查询应返回所有文档属性,而不仅仅是过滤/排序的属性。

我能够用一个非常复杂的查询来编写这个,我正在寻找更好的替代方案。如果有用,我可以发布我的解决方案,但我不想指出可能是错误的方向。

获取一些额外的文档是可以的,比如 1000 个而不是 100 个,并在内存中进行过滤/排序。 限制不精确也可以,比如 74 而不是要求的限制 100,但离它不会太远。

额外的“软”要求:

  • 查询应该适用于多个数据库(oracle、mysql 和 sqlserver),因此除非在所有平台上都可用,否则应避免使用奇怪的分析函数
  • 应该使用 JPA(eclipselink 2.4.0 实现)

预期的输出是这样的

DOC_ID   ATTRIBUTE_NAME          VALUE
  123       state              COMPLETED
  123       creationDate       21/11/2012
  123       userid             someone
  456       state              COMPLETED
  ...

【问题讨论】:

  • 在下面查看我的答案。看看有没有帮助。

标签: sql sql-order-by limit parent-child


【解决方案1】:

啊,EAV 设计的缺陷。

试试这个。

select 
   top 100
   document.* 

from document   
    inner join attribute astate on document.id = astate.doc_fk
          and astate.name='state'
          and astate.value = 'completed'
    inner join attribute acreation on document.id = acreation.doc_fk
            and acreation.name='creationdate'
order by cast(acreation.value as date)

但如果你坚持使用这种 EAV 结构,它只会变得更加复杂。

(PS. MySQL 不使用 TOP,而是使用 LIMIT)

【讨论】:

  • 我认为这不是提取文档的所有属性。
【解决方案2】:
SELECT doc_id, attr_name, attr_val, creationDate FROM 

   (
       SELECT * FROM (
          SELECT 
             doc.id as 'doc_id', attr.name as 'attr_name', null as 'attr_val', attr.value as 'creationDate'  
          FROM 
             ATTRIBUTE attr 
          LEFT JOIN 
             DOCUMENT doc ON attr.doc_fk = doc.id 
          WHERE 
             attr.name='creationDate' 
          ORDER BY creationDate desc;

       ) AS dt1


     UNION ALL


      SELECT * FROM( 
          SELECT 
             doc.id as 'doc_id', attr.name as 'attr_name', attr.value as 'attr_val', null as 'creationDate'  
          FROM 
             ATTRIBUTE attr 
          LEFT JOIN 
             DOCUMENT doc ON attr.doc_fk = doc.id;
      ) as dt2


   ) as dt0 GROUP BY doc_id ORDER by creationDate desc LIMIT 100;

派生表 1 (dt1) 为您提供所有日期属性 - 以便按文档的创建日期对结果进行排序。 派生表 2 为您提供所有属性.. 全部按“联合所有”放在一起,使您能够按文档分组,然后按创建日期排序。 希望这是正确的方向。

【讨论】:

  • 我认为这不是提取文档的所有属性,而 creationDate 是另一个表中的属性,而不是 DOCUMENT 上的列。
  • 我已经编辑了我之前的答案。派生表 1 (dt1) 为您提供所有日期属性 - 以便按文档的创建日期对结果进行排序。派生表 2 为您提供所有属性.. 全部由“联合所有”组合在一起,使您能够按文档分组,然后按创建日期排序。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-10-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-07
  • 1970-01-01
相关资源
最近更新 更多