【问题标题】:SQL group - limitSQL 组 - 限制
【发布时间】:2011-06-23 17:26:15
【问题描述】:

有时找到传达“问题”的最佳方式与找到解决方案一样困难......哈哈,但这里是......

我有一张公司表,我有一张相关表,其中包含每家公司的一些历史...... 我想返回一个查询,其中包含每家公司最后 3 个“历史”条目的记录集...

所以记录集看起来像这样......

company A
  history Az
  history Ay
  history Ax
company B
  history Bz
  history By
  history Bx
company C
  history Cz
  history Cy
  history Cx

我遇到的问题是,如果我 LIMIT 3 - 连接在那里,我只获取所有记录的最后 3 条记录,而不是每个公司的最后 3 条记录...

这是我最后一次尝试的方法 - 但它只是撤回了一家公司,3 条记录.. 就是这样......(IBM DB2 9 - 但唯一应该影响的是语法限制为 3.. )

SELECT 
   C.CompanyName   
  ,H.*

FROM Companies C
JOIN CompanyTypes CT ON C.fkTypeID = CT.ID

INNER JOIN (
    SELECT   sCH.*
    FROM     CompanyHistory sCH
    ORDER BY sCH.DATE DESC 
    FETCH FIRST 3 ROWS ONLY
) H ON H.fkCompanyID = C.ID 


WHERE CT.Type = 'bookstore'

我做错了什么?

【问题讨论】:

  • 顺便说一句 - 将我的 INNER JOIN 更改为 LEFT OUTER JOIN 返回所有公司,但只有 FIRST 公司的前 3 条记录,它忽略了其他公司的历史......
  • 问题在于您将记录数从CompanyHistory 限制为3 无论公司如何。您需要将 3 行限制移到联接之外。我会考虑一下并回复你。

标签: sql db2 limit


【解决方案1】:
SELECT C.CompanyName,H.*
FROM Companies C
JOIN CompanyTypes CT ON C.fkTypeID = CT.ID
INNER JOIN (
    SELECT   sCH.*
    FROM     CompanyHistory sCH    
    ORDER BY sCH.DATE DESC                   -- order desc so we can count
) H ON H.fkCompanyID = C.ID 
WHERE CT.Type = 'bookstore'
  and 3>(select count(*)                     -- at most 2 previous occurances
       from CompanyHistory ich
       where ich.fkCompanyID=C.ID            -- same company
          and datediff(d,ich.date,H.date)<0) -- but dates less than the row's date

基本上,我会计算每家公司的前几行,一旦超过 2 行(+当前行为 3)就删除行。您需要按日期 desc 对 CompanyHistory 表进行排序才能正常工作。

您可能需要将datediff 替换为适合您的SQL 风格的函数,我只真正了解SQL Server。

【讨论】:

  • thx Blindy - 这行得通... DB2 中的日期差异看起来像 AND (days(H.TSPDATADATE) - days(ich.TSPDATADATE))
  • @jpmyob,我不认为days 是正确的,它返回月份中的某天,因此减去连续月份中的日期将返回相反的结果。
  • 盲人获胜...至少就访问计划和效率而言... Tom's 看起来更优雅 - 访问计划看起来更好,但这里是数字...
  • TOM 的 SQL 1,134.78 Timerons(IBS 资源/负载估计测量单位) 62,775,280 条指令 153.83 I/O BLINDY 的 SQL 153.43 timerons 4,773,045 条指令 26.56 I/O 我刚开始使用访问计划来评估我的查询 - 所以我将不知道它们是否是查询效率的“真实”指标 - 但仅考虑指令和 IO - 我不得不说数量级差异会在繁忙的环境中产生性能影响。 .. 如果有一些 DBA 可以对这个主题有所启发,请启发我。再次感谢所有帮助。
【解决方案2】:

看起来 DB2 支持带有 OVER 子句的 ROW_NUMBER()。我正在猜测语法,但希望这会为您指明正确的方向:

SELECT
    CompanyName,
    SomeColumn
FROM (
    SELECT
        C.CompanyName,
        H.SomeColumn,
        ROW_NUMBER() OVER(PARTITION BY C.ID ORDER BY CH.DATE DESC)
    FROM
        Companies C
    INNER JOIN CompanyTypes CT ON C.fkTypeID = CT.ID
    INNER JOIN CompanyHistory CH ON CH.fkCompanyID = C.ID
) AS SQ

【讨论】:

  • 谢谢汤姆——这“似乎”比 Blindy 的更经济,但我无法让语法起作用——我会坚持下去,并尝试在行动计划中进行比较以了解效率.. .
  • 我很高兴你能够让它工作。如果我的语法有问题(我不使用 DB2),请告诉我,以便我可以为将来偶然发现此答案的人修复它。
猜你喜欢
  • 1970-01-01
  • 2020-07-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多