【问题标题】:Query returning too many results查询返回太多结果
【发布时间】:2015-05-29 16:22:36
【问题描述】:

返回 a.id = 366 的预期 29 个结果的 SQL 查询

    select a.name, c.name, MAX(B.date), MAX(b.renew_date) as MAXDATE
    from boson_course c
    inner join boson_coursedetail b on (c.id = b.course_id)
    inner join boson_coursedetail_attendance d on (d.coursedetail_id = b.id)
    inner join boson_employee a on (a.id = d.employee_id)
    where a.id = 366
    GROUP BY a.name, c.name
    order by MAX(b.renew_date), MAX(b.date) desc;

下面的 SQL 代码返回 34 个结果,多个结果,其中两个不同的提供提供了相同的课程。我知道这些额外的结果是因为我将e.name 添加到要返回的列表中。但只需要包含最新日期和提供者名称的 29 个条目。

    select a.name, c.name, e.name, MAX(B.date), MAX(b.renew_date) as MAXDATE
    from boson_course c
    inner join boson_coursedetail b on (c.id = b.course_id)
    inner join boson_coursedetail_attendance d on (d.coursedetail_id = b.id)
    inner join boson_employee a on (a.id = d.employee_id)
    inner join boson_provider e on b.provider_id = e.id
    where a.id = 366
    GROUP BY a.name, c.name, e.name
    order by MAX(b.renew_date), MAX(b.date) desc;

任何人都可以修改此代码以返回单个 DISTINCT 提供者名称,并为每门课程返回 MAX(renew_date)

【问题讨论】:

  • 我很困惑,因为在提供者的 id 上添加了提供者,假设 boson_provider.id 是主键,不应该添加任何新行。 boson_provider 表中是否有可能存在两个具有相同 id 的提供程序?
  • 您想要dateMAX(renew_date)max(date) 的行,这可能不同。与往常一样,您的 Postgres 版本应该在问题中。
  • Postgres 9.0 版

标签: sql postgresql greatest-n-per-group


【解决方案1】:

尝试使用distinct on

select distinct on (a.name, c.name, e.name), a.name, c.name, e.name,
       B.date, b.renew_date as MAXDATE
from boson_course c
inner join boson_coursedetail b on (c.id = b.course_id)
inner join boson_coursedetail_attendance d on (d.coursedetail_id = b.id)
inner join boson_employee a on (a.id = d.employee_id)
inner join boson_provider e on b.provider_id = e.id
where a.id = 366
ORDER BY a.name, c.name, e.name, B.date desc
order by MAX(b.renew_date), MAX(b.date) desc;

【讨论】:

    【解决方案2】:

    这会针对(a.name, c.name) 的不同组合准确返回 一个 行:
    最新的renew_date.
    其中,最新的date(可能与全球max(date)不同!)。
    其中,字母顺序第一个e.name

    SELECT DISTINCT ON (a.name, c.name)
           a.name AS a_name, c.name AS c_name, e.name AS e_name
         , b.renew_date, b.date
    FROM   boson_course       c
    JOIN   boson_coursedetail b on c.id = b.course_id
    JOIN   boson_coursedetail_attendance d on d.coursedetail_id = b.id
    JOIN   boson_employee     a on a.id = d.employee_id
    JOIN   boson_provider     e on b.provider_id = e.id
    WHERE  a.id = 366
    ORDER  BY a.name, c.name
         , b.renew_date DESC NULLS LAST
         , b.date DESC NULLS LAST
         , e.name;
    

    结果首先按a_namec_name排序。如果您需要原始排序顺序,请将其包装在子查询中:

    SELECT *
    FROM  (<query from above>) sub
    ORDER  BY renew_date DESC NULLS LAST
            , date DESC NULLS LAST
            , a_name, c_name, e_name;
    

    DISTINCT ON的解释:

    为什么是DESC NULL LAST

    另外:不要使用基本类型名称,例如 date 广告列名称。此外,name 几乎不是一个好名字。如您所见,我们必须使用别名来使此查询有用。关于命名约定的一些一般建议:

    【讨论】:

    • 非常感谢 Erwin 的更新,就像做梦一样。并感谢您提供额外的有见地/教育链接。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-11
    • 2012-09-05
    • 2023-04-09
    相关资源
    最近更新 更多