为什么Oracle Pivot会产生不存在的结果?

时间:2019-11-28 16:42:38

标签: java sql oracle jdbc oracle12c

我管理着一个数据库,其中保存了从各个站点收集的大量气候数据。这是一个Oracle 12.2数据库,这是相关表的提要:

FACT =在特定时间进行单独测量

  • UTC_START =以UTC为单位的测量开始时间
  • LST_START =开始测量的本地标准时间(到特定站点的时间)
  • SERIES_ID =测量值所属系列的ID(从FK到SERIES)
  • STATION_ID =进行测量的站点的ID(从FK到STATION)
  • VALUE =测量值

请注意,UTC_START和LST_START始终在每个站点上具有恒定的差异(LST与UTC的偏移量)。我已经确认,在任何情况下UTC_START和LST_START之间的差异都不会超出预期。

SERIES =一系列数据的描述性数据

  • SERIES_ID =系列ID(PK)
  • NAME =系列的文本名称(例如温度)

STATION =电台的描述性数据

  • STATION_ID =工作站的ID(PK)
  • SITE_ID =站点所在站点的ID(大多数站点都有一个站点,但是少数站点有2个站点)
  • SITE_RANK =如果站点超过1个,则站点内站点的排名。
  • EXT_ID =网站的外部ID(提供给我们)

站点的EXT_ID适用于该站点上的所有站点(但除非SITE_RANK == 1,否则可能不会被填充,我知道这不是理想的,但这里不是问题),并且优先考虑排名较低站点的数据。为了将这些数据整理成可消耗的格式,我们使用PIVOT将在同一站点/时间进行的测量收集到行中。

以下是查询:

WITH
    primaries AS (
        SELECT site_id, ext_id
        FROM station
        WHERE site_rank = 1
    ),

    data as (
        SELECT d.site_id, d.utc_start, d.lst_start, s.name, d.value FROM (
            SELECT s.site_id, f.utc_start, f.lst_start, f.series_id, f.value,
                 ROW_NUMBER() over (PARTITION BY s.site_id, f.utc_start, f.series_id ORDER BY s.site_rank) as ORDINAL
                 FROM fact f
                      JOIN station s on f.station_id = s.station_id
        ) d
            JOIN series s ON d.series_id = s.series_id
            WHERE d.ordinal = 1
                AND d.site_id = ?
                AND d.utc_start >= ?
                AND d.utc_start < ?
    )

    records as (

        SELECT * FROM data
        PIVOT (
               MAX(VALUE) AS VALUE
               FOR NAME IN (
                   -- these are a few series that we would want to collect by UTC_START
                   't5' as t5,
                   'p5' as p5,
                   'solrad' as solrad,
                   'str' as str,
                   'stc_05' as stc_05,
                   'rh' as rh,
                   'smv005_05' as smv005_05,
                   'st005_05' as st005_05,
                   'wind' as wind,
                   'wet1' as wet1
                   )
                )
    )

SELECT r.*, p.ext_id
FROM records r JOIN primaries p on r.site_id = p.site_id

在这里事情变得奇怪。该查询在SQLAlchemy,IntelliJ(使用OJDBC Thin)和Orcale SQL Developer中可以完美地工作。但是,当它从我们的Java程序中运行时(相同的JDBC URL和凭据,使用普通的旧JDBC语句和结果集),则给出的结果没有意义。专门针对同一站点,它将返回具有相同UTC_START但具有不同LST_START的2行(回想一下,我已验证这100%不在FACT表中的任何位置发生)。为了确保没有奇怪的参数处理,我们为占位符测试了硬编码值,并在各个客户端之间复制并粘贴了完全相同的查询,唯一返回这些奇怪结果的查询是Java程序(它使用的是与IntelliJ完全相同的OJDBC jar)。

如果任何人有任何见识或可能的原因,将不胜感激。我们现在有点茫然。

1 个答案:

答案 0 :(得分:0)

事实证明Nathan's comment是正确的。尽管似乎违反直觉(至少对我而言),但似乎在DATE列上调用ResultSet.getString实际上将首先转换为Timestamp。除非您另外明确指定,否则时间戳具有使用系统默认时区的默认默认行为。

此默认行为意味着我们不希望将夏令时考虑在内,从而导致了所描述的奇怪行为。