4

如何通过一个 SQL 查询获取一列中最新值更改的日期?

可能的数据库情况:

Date        State

2012-11-25  state one
2012-11-26  state one
2012-11-27  state two
2012-11-28  state two
2012-11-29  state one
2012-11-30  state one

所以结果应该返回 2012-11-29 作为最新的更改状态。如果我按状态值分组,我将在数据库中第一次获得该状态的日期。

该查询将按状态对表进行分组,并在日期字段中显示该状态的最新创建日期。

从给定的输入输出将是

Date               State

2012-11-30        state one
2012-11-28        state two
4

7 回答 7

2

这将为您提供最后一个状态:

-- Query 1
SELECT state
FROM tableX 
ORDER BY date DESC
  LIMIT 1 ;

封装以上内容,我们可以使用它来获取上次更改之前的日期:

-- Query 2
SELECT t.date
FROM tableX AS t
  JOIN
    ( SELECT state
      FROM tableX 
      ORDER BY date DESC
        LIMIT 1
    ) AS last
    ON last.state <> t.state
ORDER BY t.date DESC
    LIMIT 1 ;

然后使用它来查找最后一次更改发生的日期(或整行):

-- Query 3
SELECT a.date                         -- can also be used:   a.*
FROM tableX AS a 
  JOIN
    ( SELECT t.date
      FROM tableX AS t
        JOIN
          ( SELECT state
            FROM tableX 
            ORDER BY date DESC
              LIMIT 1
          ) AS last
          ON last.state <> t.state
      ORDER BY t.date DESC
          LIMIT 1
    ) AS b
    ON a.date > b.date
ORDER BY a.date
  LIMIT 1 ; 

SQL-Fiddle中测试


还有一个使用 MySQL 变量的解决方案:

-- Query 4
SELECT date
FROM
  ( SELECT t.date
         , @r := (@s <> state) AS result 
         , @s := state AS prev_state
    FROM tableX AS t
      CROSS JOIN
        ( SELECT @r := 0, @s := '' 
        ) AS dummy 
    ORDER BY t.date ASC 
  ) AS tmp
WHERE result = 1
ORDER BY date DESC
  LIMIT 1 ;
于 2012-12-04T15:23:11.307 回答
0

如果您一直在使用 postgres,则可以使用“LEAD .. OVER”比较同一个表中的不同行。我还没有设法在 mysql 中找到相同的功能。

有点毛茸茸,但我认为这会做:

select min(t1.date) from table_1 t1 where 
  (select count(distinct state) from table_1 where table_1.date>=t1.date)=1

基本上,这是第一次要求没有为任何后来的值找到状态变化。请注意,对于大型数据集,此查询可能会严重扩展......

于 2012-12-04T14:39:31.717 回答
0

如果您添加另一列“更改日期时间”,则可以使用插入 NOW() 的更新触发器来填充此列。如果您在更改的列上查询表排序,它将首先结束。

CREATE TRIGGER `trigger` BEFORE UPDATE ON `table` 
FOR EACH ROW
BEGIN
SET ROW.changed = NOW();
END$$
于 2012-12-04T14:04:52.390 回答
0

尝试这个 ::

Select 
    MAX(`Date`), state from mytable 

    group by state
于 2012-12-04T14:07:55.230 回答
0

我相信这是答案:

SELECT 
    DISTINCT State AS State, `Date`
FROM 
    Table_1 t1
WHERE t1.`Date`=(SELECT MAX(`Date`) FROM Table_1 WHERE State=t1.State)

...和测试:

http://sqlfiddle.com/#!2/8b0d8/5

于 2012-12-04T14:15:04.800 回答
0

我认为您最好的选择是分析功能。试试这个 - 性能方面应该没问题:

SELECT *
FROM test
WHERE my_date = (SELECT MAX (my_date)
                FROM (SELECT MY_DATE
                        FROM (  SELECT MY_DATE,
                                       STATE,
                                       LAG (state) OVER (ORDER BY MY_DATE)
                                          lag_val
                                  FROM test
                              ORDER BY MY_DATE) a
                       WHERE state != lag_val))

在内部选择中,LAG 函数在 STATE 列中获取先前的值,在外部选择中,我标记了更改的日期 - 滞后值与当前状态值不同的那些。在外面,我正在从这些更改日期中获取最新日期......我希望这是你所需要的。

于 2014-01-31T19:31:30.853 回答
-1
SELECT MAX(DATE) FROM YOUR_TABLE

上面的答案似乎不能满足 OP 的需求。

插入/更新触发器后更新的答案

DELCARE @latestState varchar;
DELCARE @latestDate date;
CREATE TRIGGER latestInsertTrigger AFTER INSERT ON myTable
FOR EACH ROW
BEGIN
    IF OLD.DATE <> NEW.date THEN 
      SET @latestState = NEW.state 
      SET @latestDate = NEW.date
    END IF
END
;

CREATE TRIGGER latestUpdateTrigger AFTER UPDATE ON myTable
FOR EACH ROW
BEGIN 
    IF OLD.DATE = NEW.date AND OLD.STATE <> NEW.STATE THEN 
      SET @latestState = NEW.state 
      SET @latestDate = NEW.date
    END IF
END
;

您可以使用以下查询来获取添加/更新的最新记录:

SELECT DATE, STATE FROM myTable
WHERE STATE = @latestState
OR DATE = @latestDate 
ORDER BY DATE DESC
;

结果:

DATE                                STATE
November, 30 2012 00:00:00+0000     state one
November, 28 2012 00:00:00+0000     state two
November, 27 2012 00:00:00+0000     state two

上述查询结果需要根据您的需要限制为 2、3 或 n。

坦率地说,您似乎想根据您提供的数据样本从两列中获取最大值。假设您的状态仅随日期增加。只有我希望如果stateinteger:D 那么两个列上的两个最大子查询的联合将很容易解决它。字符串操作正则表达式仍然可以找到状态列中的最大值。最后这种方法需要limit x。然而它仍然有漏孔无论如何,我花了一些时间来弄清楚你的需要:$

于 2012-12-04T14:04:33.027 回答