关于日期的子查询是正确的主意,但是您必须在子查询中包括列A,并将其与主表相关。我更喜欢使用显式联接,而不是将子查询嵌入WHERE语句中。无论如何,这通常更有效。
SELECT TABLE.*
FROM TABLE INNER JOIN
(SELECT A,MAX(Date) AS MaxDate FROM TABLE GROUP BY A) AS latest
ON TABLE.A = latest.A AND TABLE.date = latest.MaxDate
ORDER BY A,date
或更妙的是,我更喜欢CTE(公用表表达式)语法,因为它使单个查询更易于阅读:
WITH latest AS (
SELECT A,MAX(Date) AS MaxDate
FROM TABLE
GROUP BY A
)
SELECT TABLE.*
FROM TABLE INNER JOIN latest
ON TABLE.A = latest.A AND TABLE.date = latest.MaxDate
ORDER BY TABLE.A,TABLE.date
与其他答案的比较
MikeT的答案取决于non-standard feature的sqlite。只要您知道该解决方案与其他数据库引擎/服务器和SQL方言不兼容,就可以了。
下一个可能的陷阱实际上取决于您的实际数据和表模式(在问题详细信息中都不共享)。如果您的数据允许多个具有相同日期的行作为单个A
列值,则您问题中的条件不足以明确删除所有重复项。您将需要确定另一列,以用来解决所有剩余的重复项,但是您的问题再次没有做到这一点。
但是,在测试中,我发现我的解决方案允许未解决的重复项保留在结果中。 MikeT的解决方案消除了所有重复项,但是它通过任意排除其中一个重复项来实现。有一些方法可以修复这两种解决方案,以确保绝对选择要保留的重复项,但是除非您发布实际数据和表模式,否则我什至不会尝试这样做,以使我的答案不仅仅是猜测。很高兴到目前为止,我的回答很有用,但是您需要更好地理解数据(而不是在问题中揭示),以确保哪种解决方案实际上是最佳的。
奖金
根据我的更好判断,只是继续扩展答案...因为您应该单独进行研究...这是一个示例,说明您如何继续将其与其他查询一起使用...
WITH latest AS (
SELECT A,MAX(Date) AS MaxDate
FROM TABLE
GROUP BY A
),firstResults AS (
SELECT TABLE.*
FROM TABLE INNER JOIN latest
ON TABLE.A = latest.A AND TABLE.date = latest.MaxDate
ORDER BY TABLE.A,TABLE.date
)
SELECT otherTable.*
FROM firstResults JOIN otherTable
ON firstResults.A = otherTable.A
WHERE somecondition = 'foobar'
,
我相信,如果我了解您所写的内容,则可以使用:-
SELECT a,max(date),other FROM mytable GROUP BY a ORDER BY date;
按照:-
然后对结果集中的每个表达式分别求值一次
行组。如果表达式是聚合表达式,则为
评估组中所有行的值。否则,将评估
针对组中任意选择的一行。如果
结果集中有多个非聚合表达式,
然后对同一行评估所有此类表达式。
SQL As Understood By SQLite - SELECT
更正确地说,要消除 other 列的文物值,可以使用:-
SELECT
a /* will always be the same and isn't arbritary */,max(date) /* will be the maximum data */ AS date,(SELECT other FROM mytable WHERE a = m.a AND date = m.date) AS other
FROM mytable AS m /* AS m allows the outer query to be distinguished from the inner query */
GROUP BY a /* this effectivel removes duplicates on the a column */
ORDER BY date
;
示例:-
使用以下内容用一些生成的测试数据填充表:-
CREATE TABLE IF NOT EXISTS mytable (a TEXT,date TEXT,other);
WITH cte(count,a,date,other) AS
(
SELECT 1,1,date('now','+'||(random() % 30)||' days'),'other1'
UNION ALL SELECT count+1,abs(random()) % 20,'+'||(abs(random()) % 30)||' days'),'other'||(count+1) FROM cte LIMIT 100
INSERT INTO mytable (a,other) SELECT a,other FROM cte
;
SELECT * FROM mytable ORDER BY DATE DESC;
在这种情况下:-
然后在运行上述命令后运行以下命令
SELECT * FROM mytable WHERE a = a AND date = (SELECT MAX(date) FROM mytable);
SELECT * FROM mytable WHERE /*a = a AND*/ date = (SELECT MAX(date) FROM mytable);
/* Will only select 1 row per unique value of a BUT other will be an arbritary value not necessairlly the latest */
SELECT a,other FROM mytable GROUP BY a /* group by effectively display unique */;
SELECT
a /* will always be the same and isn't arbritary */,(SELECT other FROM mytable WHERE a = m.a AND date = m.date) AS other
FROM mytable AS m
GROUP BY a
;
前两个结果表明a = a不会执行任何操作,因为它将始终为真。
第三查询产生(无序):-
- 通过检查上一个结果中other的值来分配注记号。
- 在这种情况下,即使other的值是人为的值,这种较短的查询也可以正常工作(它们并不是真正的值,因为它们确实取决于查询计划者对查询的方式)。
第四个(更正确)产生相同的结果:-
结果2(您的原始查询)和结果3(原始无a = a)产生:-
和:-
,
如果您使用的是最新版本的sqlite(3.25或更高版本),则可以使用另一种方法,即使用row_number()
窗口函数按日期对具有相同a
值的组进行排名,然后选择第一个:
WITH cte AS
(SELECT a,row_number() OVER (PARTITION BY a ORDER BY date DESC) AS rn
FROM yourtable)
SELECT a,date
FROM cte
WHERE rn = 1;
要注意的一件事是,我注意到您提到另一个答案很慢,该查询需要mytable(a,date DESC)
上的索引才能获得最佳结果,而mytable(a,date)
上的索引可以加快查询速度。给出其他答案。
本文链接:https://www.f2er.com/3126739.html