OracleSQL:如何为查询添加特定的AND不为null或不为null

时间:2019-01-19 00:26:26

标签: sql oracle

背景故事

  • 我有三个要使用的桌子。目录表(目录),常规属性表(attribute1table)和特定属性表(attribute2table)。常规属性表在属性ID的属性(attrid = 2)下保存属性名称(例如姓氏)。特定属性表包含这些属性(例如Doe)的特定数据。
  • 我需要将行转置为列。我之前曾尝试使用数据透视和max(decode),但是所有选项给我的字符串值都不正确-因此我在select语句中使用了子选择。效果很好-确实将行转置为列,但给了我一堆空值。请参阅底部的查询以获取步骤。
  • 然后,我添加了一个通用的“ stringval IS NOT NULL”以消除其他任何attribute1table.attrid的属性(例如4、5、6)。这工作了。
  

这是我此时得到的输出。 ?是空值。

Name    DataID    LastName    FirstName
File10  1290      ?           Jane
File10  1290      Doe         ?
  • 然后我想添加一个规范。本质上包括LastName不为null或FirstName不为null的值。我发现有人建议在上一个问题中这样做,尽管他们的情况有所不同。 Eliminating specific null values in sql select

我能够包含一个或另一个语句,但不能同时添加两个。我没有得到任何错误,而只是获得了令人难以置信的长运行时间,没有可预见的结果(请注意,我正在使用允许您在界面内输入oracle查询以查询数据库的软件)。如果我一直运行查询直到**(请参见代码),它就会起作用,但是一旦我添加OR条件,它就不再起作用。我认为这是因为我有多个WHERE条件。在所有情况下,我都希望应用目录ID和一般stringval条件,但是我想拥有第三个条件,即姓氏不为null或名字不为null。我不确定是否缺少明显的东西-请帮忙吗?

这是我当前的查询:

SELECT directory.name, directory.dataid,
(SELECT max(stringval) FROM attribute2table WHERE attribute1table.attrid = 2) as LastName,
(SELECT max(stringval) FROM attribute2table WHERE attribute1table.attrid = 3) as FirstName

FROM attribute2table
JOIN directory ON directory.dataid = attribute2table.id
JOIN attribute1table ON attribute1table.id = directory.dataid
WHERE directory.dataid = 1290
AND stringval IS NOT NULL
AND (SELECT max(valstr) FROM attribute1table WHERE attribute1table.attrid = 2) IS NOT NULL
**OR (SELECT max(valstr) FROM attribute1table WHERE attribute1table.attrid = 3) IS NOT NULL**

基本上,我只需要摆脱null值,并希望我的表看起来像...。

Name      DataID    LastName    FirstName
File10    1290      Doe         Jane

2 个答案:

答案 0 :(得分:1)

这似乎是括号问题。如果我了解此问题,则需要将两个IS NOT NULL条件放在括号中:

SELECT directory.name,
       directory.dataid, 
       m2.LastName, 
       m3.FirstName
  FROM attribute2table
  INNER JOIN directory
    ON directory.dataid = attribute2table.id
  INNER JOIN attribute1table
    ON attribute1table.id = directory.dataid
  LEFT OUTER JOIN (SELECT max(valstr) AS LASTNAME
                     FROM attribute1table
                     WHERE attribute1table.attrid = 2) m2
    ON 1 = 1
  LEFT OUTER JOIN (SELECT max(valstr) AS FIRSTNAME
                     FROM attribute1table
                     WHERE attribute1table.attrid = 3) m3
    ON 1 = 1
  WHERE directory.dataid = 1290 AND
        stringval IS NOT NULL AND
        (m2.LASTNAME IS NOT NULL OR
         m3.FIRSTNAME IS NOT NULL)

我还使用联接而不是子选择重写了查询,因为我认为这更清楚了。

还请注意,在M2M3的联接中,我以LEFT OUTER为条件使用1 = 1而不是使用CROSS JOIN,因为我注意到了如果交叉连接的查询不返回任何行,则CROSS JOIN的行为类似于INNER JOIN,也就是说,它导致整个SELECT不返回任何数据。 dbfiddle demonstrating this situation here

答案 1 :(得分:0)

我很确定您只需要条件聚合:

SELECT d.name, d.dataid,
       MAX(CASE WHEN a1.attrid = 2 THEN a2.stringval END) as LastName,
       MAX(CASE WHEN a1.attrid = 3 THEN a2.stringval END) as FirstName
FROM directory d JOIN
     attribute2table a2
     ON a2.id = d.dataid JOIN
     attribute1table a1
     ON a1.id = d.dataid
WHERE d.dataid = 1290
GROUP BY d.name, d.dataid