【问题标题】:Query only numeric values of the earliest possible date仅查询最早可能日期的数值
【发布时间】:2014-10-02 15:14:33
【问题描述】:

我必须从 oracle 11 数据库查询。 通过下面的查询,我可以从我的数据库中获取所有最近的 TAG_VALUE, TAG_DESC, INSERTION_DATE and PROJECT_ID

SELECT * 
FROM   (SELECT t.tag_value, 
               t.tag_desc, 
               u.update_as_of                    AS INSERTION_DATE, 
               p.proj_id                         AS PROJECT_ID, 
               Row_number() 
                 over( 
                   PARTITION BY p.proj_id 
                   ORDER BY u.update_as_of DESC) RN 
        FROM   project p 
               join update u 
                 ON p.project_id = u.project_id 
               join tag t 
                 ON t.tag_id = u.tag_id 
        WHERE  t.tag_desc LIKE 'Equity%') 
WHERE  rn = 1;

但是,我遇到了这样的情况,即我的请求的答案(不按日期排序)可能如下所示:

+----------------------------------------------+
| TAG_VALUE TAG_DESC INSERTION_DATE PROJECT_ID |
+----------------------------------------------+
| null        Equity  14-DEC-14       1        |
| 0           Equity  14-DEC-14       1        |
| 312         Equity  14-DEC-14       1        |
| 23343       Equity  17-DEC-11       5        |
| 1263        Equity  16-DEC-11       5        |
| null        Equity  22-JÄN-14       2        |
| null        Equity  11-JÄN-14       2        |
| null        Equity  25-SEPT-13      2        |
| 0           Equity  20-SEPT-13      2        |
| 1234        Equity  19-SEPT-13      2        |
| 13415       Equity  18-SEPT-13      2        |
| 99999       Equity  16-OCT-10       9        |
+----------------------------------------------+

我的Result Set 应该是这样的:

+----------------------------------------------+
| TAG_VALUE TAG_DESC INSERTION_DATE PROJECT_ID |
+----------------------------------------------+
| 312         Equity  14-DEC-14       1        |
| 23343       Equity  17-DEC-11       5        |
| 1234        Equity  19-SEPT-13      2        |
| 99999       Equity  16-OCT-10       9        |
+----------------------------------------------+

有两种情况,基本上都是针对同一个问题:

  • 如您所见,有两种情况,当project_id = 1 插入日期始终相同时。但是,通过上面的查询,由于ordering,我仍然得到null。如何在不获取 null0 值的情况下找回号码 312
  • 如果projectID = 2 存在不同的插入日期,并且较早的日期具有TAG_VALUE null 元素。但是,我想要| 1234 Equity 19-SEPT-13 2 |tagValue,因为它是最新值?

如何,我基本上可以忽略所有null0 值,只取大于0 值且日期最早的数字吗?

非常感谢您的回答!

【问题讨论】:

  • 您能否更正您的查询:FROM project p FROM updated u
  • TAG_VALUE 是 VARCHAR2 还是 NUMBER?这看起来像一个 EAV 模型,如果您使用的是通用数据类型,答案会复杂得多。
  • @JonHeller TAG_Value 是 NUMERIC。 EAV 模型是什么意思?
  • 实体-属性-值。这是数据库中常见的反模式,通常会导致将所有值存储为字符串。幸好你没有上当!我之前看到过 EAV 模型使用那些完全相同的列名,这就是我问的原因。

标签: sql oracle oracle11g


【解决方案1】:

考虑到您的分组发生在 INSERTION_DATE DESC 的 PROJECT_ID 和正 TAG_VALUE 中,我调整了分析函数以实现结果。这可能不是一个可靠的解决方案,但肯定会对您有所帮助。

数据设置:

CREATE TABLE Table1
    ("TAG_VALUE" varchar2(5), "TAG_DESC" varchar2(6), "INSERTION_DATE" varchar2(10), "PROJECT_ID" int)
;

INSERT ALL 
    INTO Table1 ("TAG_VALUE", "TAG_DESC", "INSERTION_DATE", "PROJECT_ID")
         VALUES (NULL, 'Equity', '14-DEC-14', 1)
    INTO Table1 ("TAG_VALUE", "TAG_DESC", "INSERTION_DATE", "PROJECT_ID")
         VALUES ('0', 'Equity', '14-DEC-14', 1)
    INTO Table1 ("TAG_VALUE", "TAG_DESC", "INSERTION_DATE", "PROJECT_ID")
         VALUES ('312', 'Equity', '14-DEC-14', 1)
    INTO Table1 ("TAG_VALUE", "TAG_DESC", "INSERTION_DATE", "PROJECT_ID")
         VALUES ('23343', 'Equity', '17-DEC-11', 5)
    INTO Table1 ("TAG_VALUE", "TAG_DESC", "INSERTION_DATE", "PROJECT_ID")
         VALUES ('1263', 'Equity', '16-DEC-11', 5)
    INTO Table1 ("TAG_VALUE", "TAG_DESC", "INSERTION_DATE", "PROJECT_ID")
         VALUES (NULL, 'Equity', '22-JÄN-14', 2)
    INTO Table1 ("TAG_VALUE", "TAG_DESC", "INSERTION_DATE", "PROJECT_ID")
         VALUES (NULL, 'Equity', '11-JÄN-14', 2)
    INTO Table1 ("TAG_VALUE", "TAG_DESC", "INSERTION_DATE", "PROJECT_ID")
         VALUES (NULL, 'Equity', '25-SEPT-13', 2)
    INTO Table1 ("TAG_VALUE", "TAG_DESC", "INSERTION_DATE", "PROJECT_ID")
         VALUES ('0', 'Equity', '20-SEPT-13', 2)
    INTO Table1 ("TAG_VALUE", "TAG_DESC", "INSERTION_DATE", "PROJECT_ID")
         VALUES ('1234', 'Equity', '19-SEPT-13', 2)
    INTO Table1 ("TAG_VALUE", "TAG_DESC", "INSERTION_DATE", "PROJECT_ID")
         VALUES ('13415', 'Equity', '18-SEPT-13', 2)
    INTO Table1 ("TAG_VALUE", "TAG_DESC", "INSERTION_DATE", "PROJECT_ID")
         VALUES ('99999', 'Equity', '16-OCT-10', 9)
SELECT * FROM dual
;

查询:

SELECT tag_value, 
       tag_desc, 
       insertion_date, 
       project_id 
FROM   (SELECT tag_value, 
               tag_desc, 
               insertion_date, 
               project_id, 
               Last_value(Decode(tag_value, 0, NULL, 
                                            tag_value) ignore nulls) 
                 over ( 
                   PARTITION BY project_id 
                   ORDER BY insertion_date ROWS BETWEEN unbounded preceding AND 
                 unbounded 
                 following ) new_tag_value 
        FROM   table1) 
WHERE  tag_value = new_tag_value; 

结果:

TAG_VALUE   TAG_DESC    INSERTION_DATE  PROJECT_ID
312         Equity      14-DEC-14       1
1234        Equity      19-SEPT-13      2
23343       Equity      17-DEC-11       5
99999       Equity      16-OCT-10       9

这里是fiddle

【讨论】:

    【解决方案2】:

    您的问题是:“如何,我基本上可以忽略所有 null 和 0 值”

    简单的答案是:通过删除 WHERE 子句中的那些记录。

    我在这里使用AND t.tag_value > 0。如果要允许负值,可以将其替换为 AND t.tag_value <> 0 AND t.tag_value IS NOT NULL

    SELECT * 
    FROM 
    (
      SELECT 
        t.tag_value,
        t.tag_desc, 
        u.update_as_of AS INSERTION_DATE, 
        p.proj_id AS PROJECT_ID, 
        ROW_NUMBER() OVER(PARTITION BY p.proj_id ORDER BY u.update_as_of DESC) RN
      FROM updated u 
      JOIN project p ON p.project_id = u.project_id  
      JOIN tag t ON t.tag_id = u.tag_id 
      WHERE t.tag_desc LIKE 'Equity%' AND t.tag_value > 0
    )
    WHERE RN = 1;
    

    【讨论】:

      【解决方案3】:

      您可以在表中的内部查询中选择 min(Insertion_Date) 和项目 ID,并通过 Tag_Value Null 对其进行过滤。然后你在外部查询中,在 project_id 和 insert_date 上用这个内部查询内部连接表。

      【讨论】:

      • 能否通过示例查询添加一个示例? select the min(Insertion_Date) and the project ID in an inner query from the table and filter the it by Tag_Value <> Null. 到底是什么意思
      • Select * from table join (Select PROJECT_ID, min(INSERTION_DATE) from table where Tag_Value Null group by project ID)
      • Select * from table t1 join (Select PROJECT_ID, min(INSERTION_DATE) from table where Tag_Value Null group by project ID) t2 on t1.Project_id = t2.project_id and t1.insertion_date = t2。 insert_date 这里的“表”可以是您的实际表或您在问题中提到的选择语句。
      【解决方案4】:

      用例 1:

      如果我正确理解了您的用例,您可以通过分析函数排序子句中的非空非零 tag_value-s 的“优先级”来实现,如下所示:

      ROW_NUMBER() OVER (
          PARTITION BY p.proj_id
          ORDER BY
              CASE WHEN t.tag_value > 0 THEN 0 ELSE 1 END ASC,
              u.update_as_of DESC
      ) RN
      

      当然,每当p.proj_id 标识的数据分区中没有其他tag_value-s 时,这将在您的输出中为您提供null-s 或零。


      用例 2:

      如果您想完全摆脱零和null-s,则必须改为修改(内部)查询的where 子句:

      WHERE t.tag_desc LIKE 'Equity%'
          AND t.tag_value > 0
      

      【讨论】:

        猜你喜欢
        • 2016-04-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-21
        • 1970-01-01
        • 2015-05-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多