2014-12-24 72 views
0

根据属性按降序进行分组,但按升序排序的最佳方式是什么?Sqlite:选择,根据一个属性desc分组。并根据另一个排序

CREATE TABLE IF NOT EXISTS 
logs (id INTEGER NOT NULL, 
     prompt INTEGER NOT NULL, 
     value TEXT, 
PRIMARY KEY (id)); 

INSERT INTO logs(id, prompt, value) VALUES(1, 10, "a"); 
INSERT INTO logs(id, prompt, value) VALUES(2, 4, "a"); 
INSERT INTO logs(id, prompt, value) VALUES(3, 10, "b"); 
INSERT INTO logs(id, prompt, value) VALUES(4, 6, "c"); 
INSERT INTO logs(id, prompt, value) VALUES(5, 5, "c"); 
INSERT INTO logs(id, prompt, value) VALUES(6, 4, "d"); 
INSERT INTO logs(id, prompt, value) VALUES(7, 4, "e"); 
INSERT INTO logs(id, prompt, value) VALUES(8, 10, "a"); 
INSERT INTO logs(id, prompt, value) VALUES(9, 10, "z"); 

现在,我想是要的请求:根据提示(只有一个每个不同的提示行)

  1. 只保留与最大行ID

  2. 按升序排序ID(我不需要保留)

所以在这里我需要

prompt | value 
    10 | "z" 
    4 | "e" 
    6 | "c" 
    5 | "c" 

这怎么可能?以及如何使它不太低效?你可以避免一个中间请求(即从select中选择 - 我觉得可能是这样做的方式,但不知道如何)。

UPDATE:最好我能想出是做一个中间查询,并使用MIN操作:

SELECT MIN(id), prompt, lvalue 
FROM logs 
INNER JOIN 
    (SELECT prompt as lprompt, value as lvalue 
    FROM logs 
    GROUP BY prompt ORDER BY id DESC) 
ON 
    prompt = lprompt 
GROUP BY prompt ORDER BY id ASC; 

它的工作原理,但我不禁觉得这是一个坏的解决方案。

更新2:我想澄清,我想这会出现一个提示第一 ID,并与它出现在最后值;然后按照第一个ID的升序进行整个排序。

id |prompt | value 
1 | 10 | "z" 
2 | 4 | "e" 
4 | 6 | "c" 
5 | 5 | "c" 
+0

我希望更好的东西,这就是为什么我问的问题摆在首位。 –

回答

1

你可以尝试:

select minid, lprompt, lvalue from 
(SELECT prompt as lprompt, value as lvalue, min(id) as minid, max(id) as maxid 
FROM logs 
GROUP BY prompt ORDER BY id DESC) sq 
order by minid 

SQLFiddle here.

+0

选择一个不在'group by'中的列(在这种情况下为'value'),并试图通过'order by'来选择组中哪个值是被选中的,这是一个常见的错误,因为即使db可以自由返回组中的任何值。也就是说,您不能强制它通过执行'order by id desc'来返回与最大id相关联的值。 “...从组内任意选择行”https://www.sqlite.org/lang_select.html#resultset。这同样适用于mysql https://dev.mysql.com/doc/refman/5.0/en/group-by-handling.html – FuzzyTree

+0

@Mark Ba​​nnister:谢谢你的回答。从长远来看,这是最好的。你只介意提醒我max(id)是什么意思? –

+1

@Jérémie:在子查询中作为'lvalue'返回的值由优化器决定 - 没有任何聚合函数(例如'min'或'max'),这由ORDER BY'子句设置。单独使用'min'函数会覆盖这种行为,因为如果在'prompt'中按'id'升序排列结果集,查询会变得更加高效;然而,通过向子查询添加一个“max”函数,这种优化被取消,并且顺序再次由'ORDER BY'子句确定。 (你可以看到如果你运行没有'max'函数的查询会发生什么)。 –

1

查询中使用不存在来选择提示和值具有最大ID

select prompt, value 
from logs l1 
where not exists (
    select 1 from logs l2 
    where l2.prompt = l1.prompt 
    and l2.id > l1.id 
) 
order by l1.id 

或使用子查询,以直接选择每个提示

select prompt, value 
from logs l1 
where id = (
    select max(id) from logs l2 
    where l2.prompt = l1.prompt 
) 
order by l1.id 

最大ID来选择将提示值绑定到最大的id并通过提示最小的编号排序结果编号

select t1.prompt, t2.value from (
    select prompt, min(id) minid, max(id) maxid 
    from logs 
    group by prompt 
) t1 join logs t2 on t1.maxid = t2.id 
order by t1.minid 

http://sqlfiddle.com/#!7/cac0b

+0

什么是l1和l2? –

+0

@Jérémie他们是桌子别名 – FuzzyTree

+0

谢谢!然而,这并不完全正确,如果我使用ASC顺序,我尝试了第一个,我得到[(6,c),(5,c),(4,e),(10,z)];和[(10,z),(4,e),(5,c),(6,c)]如果我使用DESC顺序。但我想要的顺序是提示首次出现的顺序,即[10,4,6,5](注意6和5是相互颠倒的)。 –

相关问题