我该如何进行SQL查询,如果没有记录则返回null,如果有记录则返回值?

时间:2018-11-15 18:20:24

标签: sql sqlite android-sqlite

我正在尝试对三个不同的表进行查询。

  1. 变量表

    • 变量表包含有关"area""rounds""days"变量所属。变量表还包含一个pk列。 pk用于确定记录属于哪个变量。
  2. 面积表

    • 区域表包含有关区域"name"的信息以及 区域所属的"role"。为用户分配一个角色,然后 访问特定区域。
  3. 记录表

    • 记录表包含有关已输入记录的信息。它 包含"value""alarmed""alarmType"列。您可以搜寻 获取基于变量round和day的记录。

我正在尝试在某天和某天为用户查询所有变量。 我想显示所有变量,无论是否找到记录。当前,我有一个查询,该查询仅返回具有记录的变量,而不返回没有记录的变量。

如果没有记录,则value, alarmed, and alarmType列应为空。

这是我到目前为止构建的查询:

SELECT DISTINCT variable.name, area.name AS "areaName", variable.pk, CAST(record.value AS TEXT) AS "value", record.alarmed, record.alarmType 
FROM variable, area, record 
WHERE variable.round LIKE '%,1,%' 
  AND variable.day LIKE '%,3,%' 
  AND variable.readOnly = 0 
  AND variable.area IN (SELECT pk 
                        FROM area 
                        WHERE role = (SELECT role 
                                      FROM user 
                                      WHERE userName LIKE 'Leo')) 
  AND variable.area = area.pk 
  AND record.value = (SELECT CASE WHEN COUNT() < 1 THEN NULL 
                             ELSE CAST(value AS TEXT) END 
                      FROM record 
                      WHERE round = 1 
                        AND day = "11-14-2018" 
                        AND variable = variable.pk) 
ORDER BY variable.area, variable.position ASC;

当前它返回如下内容:

What this query returns

还有更多的变量,即使没有记录,我也想知道如何显示它们。

1 个答案:

答案 0 :(得分:2)

我想我明白了您要做什么。关键是使用联接(特别是OUTER联接),而不是尝试将所有表混在一起,然后找到相似之处。还有LEFTRIGHTINNER种口味(有关这些herehere的更多信息),具体取决于您认为“完整”或“主”数据集-查询的起点。

这是我了解您的人际关系的方式(如果我错了,请告诉我):

record.variable --> variable.pk
variable.area --> area.pk
area.role --> user.role

在您的情况下,您说您需要variable表中的所有记录,因此我将从此开始:

SELECT v.*
FROM variable v;

然后,您可能会找到与特定USER相关的所有AREA记录。使用INNER联接仅查找联接两边都存在的记录:

SELECT a.*, u.*
FROM area a
INNER JOIN user u         -- Define the table to join
   ON a.role = u.role     -- Which columns contain keys to match on
WHERE u.userName = 'Leo';

WHERE过滤器适用于user表,但是因为我们仅从area表中查询与用户匹配的记录,所以这限制了{{1} }表。

下一步是使用另一个area连接再次将这两个提取物连接在一起,以找到交集-在连接的两边都存在的匹配项:

INNER

现在,我们通过添加SELECT v.*, a.*, u.* FROM variable v -- New starting point INNER JOIN area a ON a.pk = v.area INNER JOIN user u ON a.role = u.role WHERE u.userName = 'Leo'; 子句来查找某天的所有记录:

WHERE

接下来,我们使用SELECT v.*, a.*, u.* FROM variable v INNER JOIN area a ON a.pk = v.area INNER JOIN user u ON a.role = u.role WHERE u.userName = 'Leo' AND v.round = 1 -- Add filters for "round" AND v.day = '11-14-2018'; -- and "day" columns 联接为我们提供“左侧”表中的所有记录,以及在“右侧”(“记录”表)中找到的所有匹配项;如果没有,则为NULL匹配:

LEFT

来自SELECT v.name ,a.name as "areaName" ,CAST(r.value as TEXT) as "value" ,r.alarmed ,r.alarmType FROM variable v INNER JOIN area a ON v.area = a.pk INNER JOIN user u ON a.role = u.role LEFT JOIN record r -- LEFT is important here ON v.pk = r.variable WHERE u.userName = 'Leo' AND v.round = 1 AND v.day = '11-14-2018' ORDER BY v.area, v.position; 连接(INNER + variable + area)的结果成为此连接的“左侧”,而user成为该连接的“左侧”。 “右边。使用record连接声明我们希望从左侧开始的所有记录,无论它们是否在右侧都匹配。

我没有数据集可用于测试,因此请原谅我犯的任何错误。

希望这说明如何将联接用于消除行并向结果添加数据(列),而不必进行单个查询或诉诸子查询(使用LEFTIN )。