SELECT DISTINCT返回的行数多于预期

时间:2014-08-28 12:28:00

标签: sql greatest-n-per-group

我在这里已经阅读了很多答案,但直到现在还没有什么可以帮助我。我正在开发一个票务系统,每张票都有很多更新。

我有大约2个表:tb_tickettb_updates

我用子查询创建了一个SELECT,花了很长时间(大约25秒)来获得大约1000行。现在我在子查询中将其更改为INNER JOIN而不是SELECT,它实际上很快(70毫秒),但现在我得到了重复票证。我想知道如何才能获得最后一行(按时间排序)。

我目前的结果是:

...
67355;69759;"COMPANY X";"2014-08-22 09:40:21";"OPEN";"John";1
67355;69771;"COMPANY X";"2014-08-26 10:40:21";"UPDATE";"John";1

第一列是故障单ID ,第二列是更新ID ...我希望每个故障单ID只能获得一行,但是DISTINCT没有在这种情况下工作。应该是哪一行?总是最新的,所以在这种情况下 2014-08-26 10:40:21

更新 这是一个postgresql数据库。我没有分享我当前的查询,因为它只有葡萄牙语名称,所以我认为它根本没用。

解: Used_By_Already 是我问题的最佳解决方案。

4 个答案:

答案 0 :(得分:3)

如果没有表格的详细信息,就必须猜测字段名称,但似乎tb_updates在tb_ticket中有多条记录(多对一关系)。

您的问题的通用解决方案 - 只获取“最新”记录 - 是在tb_updates上使用子查询(请参阅下面的别名mx),然后将其连接回tb_updates,以便只有具有最新日期的记录是选择的。

SELECT
      t.*
    , u.*
FROM tb_ticket t
      INNER JOIN tb_updates u
                  ON t.ticket_id = u.ticket_id
      INNER JOIN (
                  SELECT
                        ticket_id
                      , MAX(updated_at) max_updated
                  FROM tb_updates
                  GROUP BY
                        ticket_id
            ) mx
                  ON u.ticket_id = mx.ticket_id
                        AND u.updated_at = mx.max_updated
;

如果你有一个支持ROW_NUMBER()的dbms,那么使用该函数可能是一种非常有效的替代方法,但你还没有告诉我们你正在使用哪个dbms。


顺便说一下: 这些行是不同的:

67355;69759;"COMPANY X";"2014-08-22 09:40:21";"OPEN";"John";1
67355;69771;"COMPANY X";"2014-08-26 10:40:21";"UPDATE";"John";1

69759与69771不同,这足以让2行成为DISTINCT 两个日期也有差异。

distinct是row operator,这意味着在决定哪些行是唯一的时,会考虑整行,而不仅仅是第一列。

答案 1 :(得分:1)

Used_By_Already的解决方案可以正常工作。我不确定性能,但另一个解决方案是使用交叉应用,但这仅限于几个DBMS。

SELECT *
FROM tb_ticket ticket
CROSS APPLY (
    SELECT top(1) *
    FROM tb_updates details
    ORDER BY updateTime desc
    WHERE details.ticketID = ticket.ticketID
    ) updates

答案 2 :(得分:0)

如果您的updateid是标识列,可以尝试类似下面的内容:

Select ticketed, max(updateid) from table
group by ticketed

答案 3 :(得分:0)

要获取最后一行,您必须使用order by time desc结束查询,然后在select语句中使用TOP (1)以仅选择查询结果中的第一行

例如:

select TOP (1) .....
       from .....
       where .....
       order by time desc