我有两个表详细信息和数据表。 我已经加入了两个表,交叉表功能已经完成。
我想只显示每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);
我需要加入serial
和date
上的两个表格。
我认为 DISTINCT ON
可能对此有所帮助,但当我使用DISTINCT ON serial
时,我似乎无法获得正确的结果。
答案 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,DISTINCT
和DISTINCT 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
但是,如果预计这些数据与您的样本数据遵循相同的原则,那么这仅适用于您的数据。否则,也许你可以更好地解释你拥有什么样的数据以及你想要的输出。