将交叉表功能与DISTINCT ON

时间:2016-05-23 01:36:24

标签: sql postgresql distinct greatest-n-per-group crosstab

我有两个表详细信息数据表。 我已经加入了两个表,交叉表功能已经完成。

我想只显示每serial的最新数据。请参阅下面的当前和所需输出。

问题: 如何在此交叉表查询中使用DISTINCT ON

details

serial   | date                 |    line      |   total_judgement
---------+----------------------+--------------+----------------
 123     | 2016/05/21 12:00:00  |      A       |       1
 456     | 2016/05/21 12:02:00  |      A       |       0
 456     | 2016/05/21 12:05:00  |      A       |       0

data

serial   |     date             | readings   |   value
---------+----------------------+------------+-------------
 123     | 2016/05/21 12:00:00  | reading1   |  1.2342
 123     | 2016/05/21 12:00:00  | reading2   |  2.3213
 123     | 2016/05/21 12:00:00  | reading3   |  3.4232
 456     | 2016/05/21 12:00:02  | reading1   |  1.2546
 456     | 2016/05/21 12:00:02  | reading2   |  2.3297
 456     | 2016/05/21 12:00:02  | reading3   |  3.4264
 456     | 2016/05/21 12:00:05  | reading1   |  1.9879
 456     | 2016/05/21 12:00:05  | reading2   |  2.4754
 456     | 2016/05/21 12:00:05  | reading3   |  3.4312

当前输出:

serial   | line |      date            | total_judgement| reading1  |   reading2  |   reading3  
---------+------+----------------------+----------------+-----------+-------------+--------------
123      |  A   |  2016/05/21 12:00:00 |       1        |  1.2342   |   2.3213    |   3.4232      
456      |  A   |  2016/05/21 12:00:02 |       0        |  1.2546   |   2.3297    |   3.4264 
456      |  A   |  2016/05/21 12:00:02 |       0        |  1.9879   |   2.4754    |   3.4312    

期望输出:

serial   | line |     date             | total_judgement | reading1  |   reading2  |   reading3   
---------+------+----------------------+-----------------+-----------+-------------+--------------
123      |  A   |  2016/05/21 12:00:00 |         1       |  1.2342   |   2.3213    |   3.4232  
456      |  A   |  2016/05/21 12:00:05 |         0       |  1.9879   |   2.4754    |   3.4312 

这是我的代码:

SELECT * FROM crosstab (
            $$ SELECT
                tb2.serial,
                tb1.line,
                tb2.date,
                tb1.total_judgement,
                tb2.readings,
                tb2.value
            FROM
                data tb2
                    INNER JOIN details tb1 ON (tb2.serial = tb1.serial 
             AND   tb2.date = tb1.date)
            ORDER BY tb2.date ASC $$,
            $$ VALUES ('reading1'),('reading2'),('reading3')$$
  ) as ct("S/N" VARCHAR (50),
          "Line" VARCHAR(3),
          "Date" TIMESTAMP,
          "TotalJudgement" CHARACTER(1),
          "Reading1" FLOAT8,
          "Reading2" FLOAT8,
          "Reading3" FLOAT8);

注释

我需要加入serialdate上的两个表格。

我认为 DISTINCT ON 可能对此有所帮助,但当我使用DISTINCT ON serial时,我似乎无法获得正确的结果。

2 个答案:

答案 0 :(得分:1)

做出一些假设,这可能就是你要找的东西:

SELECT * FROM crosstab (
   $$
   SELECT t2.serial
        , t1.line
        , t2.date
        , t1.total_judgement
        , t2.readings
        , t2.value
   FROM  (SELECT DISTINCT ON (serial) * FROM details ORDER BY serial, date DESC) t1
   JOIN   data t2 USING (serial, date)
   ORDER  BY t2.serial
   $$
 , $$VALUES ('reading1'),('reading2'),('reading3')$$
   ) AS ct("S/N" text
         , "Line" text
         , "Date" timestamp
         , "TotalJudgement" text
         , "Reading1" float8
         , "Reading2" float8
         , "Reading3" float8);

如果您在加入后应用DISTINCT ON (serial) ,则只会保留data中的一行。将DISTINCT步骤移至details上的子查询,以获取data所有读数,以获取serial中每个details的最新行}。

BTW,DISTINCTDISTINCT ON ( expression [, ...] )不是"功能"但SQL构造。基本信息:

在进行此操作时,我对代码进行了一些简化。对答案来说不是必不可少的。

如果表serial中每个details多个行,则使用其中一种技术代替DISTINCT ON可能更有效:

在不知道表格定义,基数等情况下,我无法更具体。

答案 1 :(得分:0)

您的代码和数据似乎都与您的"当前输出"完全匹配。 也许您可以通过以下方式使用DISTINCT ON获得所需的输出(在交叉表函数内):

SELECT DISTINCT ON (tb2.serial, tb2.readings)
       tb2.serial,
       tb1.line,
       tb2.date,
       tb1.total_judge,
       tb2.readings,
       tb2.value
FROM data tb2
JOIN details tb1 ON (tb2.serno = tb1.serno AND   tb2.date = tb1.date)
ORDER BY tb2.serial, tb2.readings, tb2.date DESC

但是,如果预计这些数据与您的样本数据遵循相同的原则,那么这仅适用于您的数据。否则,也许你可以更好地解释你拥有什么样的数据以及你想要的输出。