选择值已更改的值和列

时间:2017-06-05 19:32:50

标签: mysql sql mariadb

我有一个历史记录,每次更改1个值时记录1行。因此,在每一行中,应始终只有1个值与上一行

相比发生了变化

我的表看起来像这样。 (我有超过5列,他们没有通用名称,这些列名将为每个项目更改。我想避免硬编码列名称)

INDEX|Column1|Column2|Column3|Column4|Column5|TimeStamp 
1    |      0|      0|      0|      0|      0|2017-03-28 13:00:00
2    |      0|      0|      0|      1|      0|2017-03-28 14:00:00
3    |      2|      0|      0|      1|      0|2017-03-28 15:00:00
4    |      3|      0|      0|      1|      0|2017-03-28 16:00:00
5    |      3|     22|      0|      1|      0|2017-03-28 17:00:00
6    |      3|     22|      6|      1|      0|2017-03-28 18:00:00

我想在报告中得到的结果。

Name   |NewValue|PreviousValue|TimeStamp
Column4|       1|            0|2017-03-28 14:00:00
Column1|       2|            0|2017-03-28 15:00:00
Column1|       3|            2|2017-03-28 16:00:00
Column2|      22|            0|2017-03-28 17:00:00
Column3|       6|            0|2017-03-28 18:00:00

实现这一目标的最佳方式是什么?

我正在使用MariaDB 10.1.22。

2 个答案:

答案 0 :(得分:0)

SELECT 'Column5', column5, max(timestamp) from mytable where column5 <> 0 group by column5
Union
SELECT 'Column4', column4, max(timestamp) from mytable where column4 <> 0 group by column4
Union
SELECT 'Column3', column3, max(timestamp) from mytable where column3 <> 0 group by column3
Union
SELECT 'Column2', column2, max(timestamp) from mytable where column2 <> 0 group by column2
Union
SELECT 'Column1', column1, max(timestamp) from mytable where column1 <> 0 group by column1

答案 1 :(得分:0)

使用静态SQL:

这是您想要的基本代码。但一切都是硬编码的。没有“动态SQL”,这是无法避免的。

language: perl
perl:
  - "5.22"

matrix:
  fast_finish: true
  allow_failures:
    - env: COVERAGE=1 USE_CPANFILE_SNAPSHOT=true
    - env: USE_CPANFILE_SNAPSHOT=false HARNESS_VERBOSE=1
env:
  global:
    # Carton --deployment only works on the same version of perl
    # that the snapshot was built from.
    - DEPLOYMENT_PERL_VERSION=5.22
    - DEVEL_COVER_OPTIONS="-ignore ^local/"
  matrix:

    # Get one passing run with coverage and one passing run with Test::Vars
    # checks.  If run together they more than double the build time.
    - COVERAGE=1 USE_CPANFILE_SNAPSHOT=true
    - USE_CPANFILE_SNAPSHOT=false HARNESS_VERBOSE=1
    - USE_CPANFILE_SNAPSHOT=true

before_install:
  - git clone git://github.com/travis-perl/helpers ~/travis-perl-helpers
  - source ~/travis-perl-helpers/init

  - npm install -g less js-beautify
  # Pre-install from backpan to avoid upgrade breakage.
  - cpanm -n http://cpan.metacpan.org/authors/id/M/ML/MLEHMANN/common-sense-3.6.tar.gz
  - cpanm -n App::cpm Carton

install:
  - cpan-install --coverage   # installs converage prereqs, if enabled
  - 'cpm install `test "${USE_CPANFILE_SNAPSHOT}" = "false" && echo " --resolver metadb" || echo " --resolver snapshot"`'

before_script:
  - coverage-setup

script:
  # Devel::Cover isn't in the cpanfile
  # but if it's installed into the global dirs this should work.
  - carton exec prove -lr -j$(test-jobs) t

after_success:
  - coverage-report

notifications:
  email:
    recipients:
      - olaf@seekrit.com
    on_success: change
    on_failure: always
  irc: "irc.perl.org#metacpan-travis"

# Use newer travis infrastructure.
sudo: false
cache:
  directories:
    - local

如果列之前或之后的列可能为SELECT CASE WHEN t1.Column1 <> t2.Column1 THEN 'Column1' WHEN t1.Column2 <> t2.Column2 THEN 'Column2' WHEN t1.Column3 <> t2.Column3 THEN 'Column3' WHEN t1.Column4 <> t2.Column4 THEN 'Column4' WHEN t1.Column5 <> t2.Column5 THEN 'Column5' END as Name, CASE WHEN t1.Column1 <> t2.Column1 THEN t2.Column1 WHEN t1.Column2 <> t2.Column2 THEN t2.Column2 WHEN t1.Column3 <> t2.Column3 THEN t2.Column3 WHEN t1.Column4 <> t2.Column4 THEN t2.Column4 WHEN t1.Column5 <> t2.Column5 THEN t2.Column5 END as NewValue, CASE WHEN t1.Column1 <> t2.Column1 THEN t1.Column1 WHEN t1.Column2 <> t2.Column2 THEN t1.Column2 WHEN t1.Column3 <> t2.Column3 THEN t1.Column3 WHEN t1.Column4 <> t2.Column4 THEN t1.Column4 WHEN t1.Column5 <> t2.Column5 THEN t1.Column5 END as PreviousValue, t2.TimeStamp FROM MyTable t1 JOIN MyTable t2 ON t2.Index = t1.Index + 1 ,则需要相应地调整NULL

使用动态SQL:

您可以通过从<>表中提取列数据来生成上述代码,而不是对列名进行硬编码。将information_schema变量设置为您要处理的表的名称,此代码将变量@tablename设置为保存与上述代码相同的代码。我已使用@sql添加新行,因此改进了生成代码中的格式。

\n

如果您对变量中的内容感到满意,可以重新运行替换最后一行:

-- Avoids the GROUP_CONCAT truncating the code we're building
SET SESSION GROUP_CONCAT_MAX_LEN=65535;

-- Specify your target table here
SELECT @tablename := 'MyTable';

SELECT @sql := GROUP_CONCAT(theCode SEPARATOR '')
FROM
(
-- theOrderBy is for keeping the various parts of this code in the correct sequence
-- SELECT plus the opening of the first CASE statement
SELECT 0 theOrderBy, 'SELECT\nCASE\n' theCode

UNION ALL

-- Generates the inner part first CASE statement
SELECT 1, CONCAT('    WHEN t1.',Column_Name,' <> t2.',Column_Name,' THEN ''', Column_Name,'''','\n')
FROM `information_schema`.`Columns`
WHERE table_name like @tablename
AND Column_Name NOT IN ('Index','Timestamp')

UNION ALL

-- Generates the end of the first CASE (and it's alias) and the beginning of the second one
SELECT 2, 'END as Name,\nCASE\n'

UNION ALL

-- Generates the inner part second CASE statement
SELECT 3, CONCAT('    WHEN t1.',Column_Name,' <> t2.',Column_Name,' THEN t2.', Column_Name, '\n')
from `information_schema`.`Columns`
WHERE table_name LIKE @tablename
AND Column_Name NOT IN ('Index','Timestamp')

UNION ALL

-- Generates the end of the second CASE (and it's alias) and the beginning of the third one    
SELECT 4, 'END as NewValue,\nCASE\n'

UNION ALL

-- Generates the inner part third CASE statement
SELECT 5, CONCAT('    WHEN t1.',Column_Name,' <> t2.',Column_Name,' THEN t1.', Column_Name, '\n')
FROM `information_schema`.`Columns`
WHERE table_name like @tablename
AND Column_Name NOT IN ('Index','Timestamp')

UNION ALL

-- Generates the end of the final CASE statement plus the FROM clause
SELECT 6, CONCAT('END as PreviousValue,\nt2.Timestamp\nFROM\n    ',@tablename, ' t1\n    JOIN ',@tablename, ' t2 ON\n        t2.Index = t1.Index + 1')

ORDER BY theOrderBy
) as sub;

SELECT @sql;

此代码的可行性在很大程度上取决于您对任何目标表具有相同的基本结构,即顺序增加PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; 字段和Index。与“静态”代码一样,这也是使用Timestamp进行所有比较,因此有效地假设每次更改之前或之后字段都不是<>

如果这些假设不成立,您需要进行调整。如果您需要帮助,请告诉我。

相关问题