生成此报告的最有效方法是什么?

时间:2011-12-15 23:49:39

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

给定一个表(daily_sales),表示以下数据/列的100k行:

id    rep   sales  date  
1     a     123    12/15/2011  
2     b     153    12/15/2011  
3     a      11    12/14/2011  
4     a     300    12/13/2011  
5     a     120    12/12/2011  
6     b     161    11/15/2011  
7     a       3    11/14/2011  
8     c      13    11/14/2011  
9     c      44    11/13/2011  

编写报告(完全在SQL中)最有效的方法是显示每个名称的两个最新条目(代表,销售,日期),因此输出将是:

a  123  12/15/2011  
a   11  12/14/2011  
b  153  12/15/2011  
b  161  11/15/2011  
c   13  11/14/2011  
c   44  11/13/2011  

谢谢!

3 个答案:

答案 0 :(得分:2)

仅供参考,您的示例主要是使用保留字,这使我们尝试编程可怕。如果您有真正的表格列,请将它们提供给我们。这是postgres:

select name,value, max(date)
from the_table_name_you_neglect_to_give_us
group by 1,2

那将给你一个名字,值,最大值(日期)的列表......虽然我不得不问为什么给我们一个名为value的列,如果它在示例中没有改变?

让我们说你确实有一个id栏...我们会与你的计划保持一致并称之为'ID'......

 select b.id from
(select name,value, max(date) date
from the_table_name_you_neglect_to_give_us
group by 1,2) a
inner join the_table_name_you_neglect_to_give_us b on a.name=b.name and a.value=b.value and a.date = b.date

这给出了最大的所有ID的列表......把它放在一起:

select name,value, max(date)
from the_table_name_you_neglect_to_give_us
group by 1,2

联合所有

select name,value, max(date)
from the_table_name_you_neglect_to_give_us
where id not in
(select b.id from
(select name,value, max(date) date
from the_table_name_you_neglect_to_give_us
group by 1,2) a
inner join the_table_name_you_neglect_to_give_us b on a.name=b.name and a.value=b.value      and a.date = b.date)

希望我的语法正确......应该无论如何都要接近。我会在整个事情周围放置一个括号,然后按名称从(查询上方)中选择...给出您想要的订单。

答案 1 :(得分:1)

对于MySQL,在 @Quassnoi's blog 中解释,(name, date)上的索引并使用此:

SELECT  t.*
FROM    (
        SELECT  name,
                COALESCE(
                (
                SELECT  date
                FROM    tableX ti
                WHERE   ti.name = dto.name
                ORDER BY
                        ti.name, ti.date DESC
                LIMIT 1 
                OFFSET 1                      --- this is set to 2-1 
                ), CAST('1000-01-01' AS DATE)) AS mdate
        FROM    (
                SELECT  DISTINCT name
                FROM    tableX dt
                ) dto
        ) tg
        , tableX t
WHERE   t.name >= tg.name
  AND   t.name <= tg.name
  AND   t.date >= tg.mdate

答案 2 :(得分:1)

如果我理解你的意思..那么这可能会有所帮助:

SELECT main.name, main.value, main.date 
FROM tablename AS main
LEFT OUTER JOIN tablename AS ctr
    ON main.name = ctr.rname
    AND main.date <= ctr.rdate
GROUP BY main.name, main.date
HAVING COUNT(*) <= 2
ORDER BY main.name ASC, main.date DESC

我知道SQL比其他帖子短,但是先尝试一下..