SQLITE选择唯一行 与其他答案的比较奖金

我有一张表,其中的行似乎是“重复项”,但实际上却不是(行的日期不同)。

假定每个记录都有一个应该是唯一的列A。但是,由于此列A以后可能会或不会再次出现更新信息(而A列保持不变),因此即使在应有的情况下它也不再唯一。

因此,我只希望该表包含最新信息。当前,该表包含50万个条目,但是唯一条目的“真实”数目少于其一半。

我尝试过

SELECT *
  FROM TABLE
    WHERE A = A  
    AND Date = (SELECT MAX(Date) from TABLE)
    ORDER BY DATE 

但是,这仅返回2个结果。我该如何实现?

qingfeng24 回答:SQLITE选择唯一行 与其他答案的比较奖金

关于日期的子查询是正确的主意,但是您必须在子查询中包括列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;

在这种情况下:-

enter image description here

  • 突出显示的行是需要提取的行。

然后在运行上述命令后运行以下命令

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不会执行任何操作,因为它将始终为真。

第三查询产生(无序):-

enter image description here

  • 通过检查上一个结果中other的值来分配注记号。
    • 在这种情况下,即使other的值是人为的值,这种较短的查询也可以正常工作(它们并不是真正的值,因为它们确实取决于查询计划者对查询的方式)。

第四个(更正确)产生相同的结果:-

enter image description here

结果2(您的原始查询)和结果3(原始无a = a)产生:-

enter image description here

和:-

enter image description here

,

如果您使用的是最新版本的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

大家都在问