查询返回太多结果

时间:2015-03-25 19:47:05

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

返回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;

任何人都可以重做此代码,以便为每个课程返回一个带有MAX(renew_date)的DISTINCT提供商名称。

2 个答案:

答案 0 :(得分:1)

根据(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几乎不是一个好名字。如您所见,我们必须使用别名来使此查询有用。关于命名约定的一些一般性建议:

答案 1 :(得分:0)

尝试使用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;