如果ID不在数据集中,则SQLite连接为零

如果ID不在数据集中,则SQLite连接为零,sql,sqlite,Sql,Sqlite,在SQLite数据库中,我有两个表,base和override,我需要在base.ID和override.BaseID上用MINoverride.Priority连接在一起。Override.BaseID可以为“0”,在这种情况下,表示覆盖是全局的,并应用于所有基本记录,除非存在具有BaseID的覆盖记录,并且具有相等或更低的Override.Priority值。也可能根本没有全局覆盖记录,这意味着我只想在存在相应的override.BaseID记录时返回基记录。我可以在内存或存储过程中执行此操

在SQLite数据库中,我有两个表,base和override,我需要在base.ID和override.BaseID上用MINoverride.Priority连接在一起。Override.BaseID可以为“0”,在这种情况下,表示覆盖是全局的,并应用于所有基本记录,除非存在具有BaseID的覆盖记录,并且具有相等或更低的Override.Priority值。也可能根本没有全局覆盖记录,这意味着我只想在存在相应的override.BaseID记录时返回基记录。我可以在内存或存储过程中执行此操作,但有没有一种方法可以在一个查询中完成所有操作

例如,以下是一些基本数据:

ID | Name
----------
1  | Test1
2  | Test2
3  | Test3
下面是一些覆盖数据:

ID | BaseID | Priority | Authorized
-----------------------------------
1  | 1      | 1        | 0
2  | 3      | 1        | 1
3  | 0      | 2        | 1
下面是我希望查询返回的内容:

base.ID | base.Name | override.ID | override.Authorized
-------------------------------------------------------
1       | Test1     | 1           | 0
2       | Test2     | 3           | 1
3       | Test3     | 2           | 1
如果我们要删除override.ID“3”,我预计会出现以下情况:

base.ID | base.Name | override.ID | override.Authorized
-------------------------------------------------------
1       | Test1     | 1           | 0
3       | Test3     | 2           | 1

首先获取每个基本ID具有最小优先级值的行。以这种方式使用MIN需要SQLite 3.7.11或更高版本

SELECT ID,
       BaseID,
       MIN(Prority) AS Priority,
       Authorized
FROM override;
然后过滤掉由于gloval覆盖而无效的任何行:

...
WHERE NOT EXISTS (SELECT 1
                  FROM override AS g
                  WHERE g.BaseID   = 0
                    AND g.Priority < override.Priority);
然后可以将其连接起来:

SELECT base.ID,
       base.Name,
       o.ID,
       o.Authorized
FROM base
JOIN (SELECT ID,
             BaseID,
             MIN(Prority) AS Priority,
             Authorized
      FROM override
      WHERE NOT EXISTS (SELECT 1
                        FROM override AS g
                        WHERE g.BaseID   = 0
                          AND g.Priority < override.Priority)
     ) AS o
     ON base.ID = o.BaseID OR o.BaseID = 0;

首先获取每个基本ID具有最小优先级值的行。以这种方式使用MIN需要SQLite 3.7.11或更高版本

SELECT ID,
       BaseID,
       MIN(Prority) AS Priority,
       Authorized
FROM override;
然后过滤掉由于gloval覆盖而无效的任何行:

...
WHERE NOT EXISTS (SELECT 1
                  FROM override AS g
                  WHERE g.BaseID   = 0
                    AND g.Priority < override.Priority);
然后可以将其连接起来:

SELECT base.ID,
       base.Name,
       o.ID,
       o.Authorized
FROM base
JOIN (SELECT ID,
             BaseID,
             MIN(Prority) AS Priority,
             Authorized
      FROM override
      WHERE NOT EXISTS (SELECT 1
                        FROM override AS g
                        WHERE g.BaseID   = 0
                          AND g.Priority < override.Priority)
     ) AS o
     ON base.ID = o.BaseID OR o.BaseID = 0;
我想到了这个:

首先,查找优先级最低的全局覆盖(如果存在),并将其内部联接到基集,以防止在没有全局覆盖的情况下返回任何基行,并在优先级中添加“.1”:

SELECT *
FROM base
JOIN (SELECT ID AS OverrideID, BaseID, Authorized, MIN(Priority) + '.1' AS Priority
    FROM override
    WHERE BaseID = 0)
SELECT *
FROM base b
JOIN (SELECT ID AS OverrideID, BaseID, Authorized, MIN(Priority) + '.0' AS Priority
    FROM override
    WHERE BaseID != 0
    GROUP BY BaseID) o ON b.ID = o.BaseID
然后查找按BaseID分组的最低优先级非全局覆盖,在base.ID上内部联接基表,并向优先级添加“.0”:

SELECT *
FROM base
JOIN (SELECT ID AS OverrideID, BaseID, Authorized, MIN(Priority) + '.1' AS Priority
    FROM override
    WHERE BaseID = 0)
SELECT *
FROM base b
JOIN (SELECT ID AS OverrideID, BaseID, Authorized, MIN(Priority) + '.0' AS Priority
    FROM override
    WHERE BaseID != 0
    GROUP BY BaseID) o ON b.ID = o.BaseID
最后,合并两个数据集并选择按base.ID分组的最低优先级值:

SELECT *, MIN(Priority)
FROM (SELECT *
    FROM base
    JOIN (SELECT ID AS OverrideID, BaseID, Authorized, MIN(Priority) + '.1' AS Priority
        FROM override
        WHERE BaseID = 0)
    UNION
    SELECT *
    FROM base b
    JOIN (SELECT ID AS OverrideID, BaseID, Authorized, MIN(Priority) + '.0' AS Priority
        FROM override
        WHERE BaseID != 0
        GROUP BY BaseID) o ON b.ID = o.BaseID)
GROUP BY ID;
如果全局覆盖和非全局覆盖的优先级相同,则连接的小数点将充当分界线,从而优先于非全局覆盖。到目前为止,这似乎是可行的。它可能会被重构以获得更高的效率,但对于我来说,它足够准确和快速

更新:

哇。嗯,我有点无聊,决定重构。我能够大大简化查询:

SELECT *, MIN(override.Priority + CASE WHEN override.BaseID = 0 THEN '.1' ELSE '.0' END)
FROM base
JOIN override ON (override.BaseID = 0 OR override.BaseID = base.ID)
GROUP BY base.ID;
我希望我不必在MIN函数中执行concat,如果我不必担心断开连接的问题,我也不需要它,但这似乎是一个很好的解决方案。

我想出了这个:

首先,查找优先级最低的全局覆盖(如果存在),并将其内部联接到基集,以防止在没有全局覆盖的情况下返回任何基行,并在优先级中添加“.1”:

SELECT *
FROM base
JOIN (SELECT ID AS OverrideID, BaseID, Authorized, MIN(Priority) + '.1' AS Priority
    FROM override
    WHERE BaseID = 0)
SELECT *
FROM base b
JOIN (SELECT ID AS OverrideID, BaseID, Authorized, MIN(Priority) + '.0' AS Priority
    FROM override
    WHERE BaseID != 0
    GROUP BY BaseID) o ON b.ID = o.BaseID
然后查找按BaseID分组的最低优先级非全局覆盖,在base.ID上内部联接基表,并向优先级添加“.0”:

SELECT *
FROM base
JOIN (SELECT ID AS OverrideID, BaseID, Authorized, MIN(Priority) + '.1' AS Priority
    FROM override
    WHERE BaseID = 0)
SELECT *
FROM base b
JOIN (SELECT ID AS OverrideID, BaseID, Authorized, MIN(Priority) + '.0' AS Priority
    FROM override
    WHERE BaseID != 0
    GROUP BY BaseID) o ON b.ID = o.BaseID
最后,合并两个数据集并选择按base.ID分组的最低优先级值:

SELECT *, MIN(Priority)
FROM (SELECT *
    FROM base
    JOIN (SELECT ID AS OverrideID, BaseID, Authorized, MIN(Priority) + '.1' AS Priority
        FROM override
        WHERE BaseID = 0)
    UNION
    SELECT *
    FROM base b
    JOIN (SELECT ID AS OverrideID, BaseID, Authorized, MIN(Priority) + '.0' AS Priority
        FROM override
        WHERE BaseID != 0
        GROUP BY BaseID) o ON b.ID = o.BaseID)
GROUP BY ID;
如果全局覆盖和非全局覆盖的优先级相同,则连接的小数点将充当分界线,从而优先于非全局覆盖。到目前为止,这似乎是可行的。它可能会被重构以获得更高的效率,但对于我来说,它足够准确和快速

更新:

哇。嗯,我有点无聊,决定重构。我能够大大简化查询:

SELECT *, MIN(override.Priority + CASE WHEN override.BaseID = 0 THEN '.1' ELSE '.0' END)
FROM base
JOIN override ON (override.BaseID = 0 OR override.BaseID = base.ID)
GROUP BY base.ID;

我希望我不必在MIN函数中执行concat,如果我不必担心断开连接,我也不需要它,但这似乎是一个很好的解决方案。

显示一些示例数据和所需的结果。@CL添加了示例数据!同一个BaseID可以有多个重写吗?@CL是的,这是可能的,所以我需要优先级最小的一个value@CL我还应该补充一点,如果全局行的优先级低于非全局行的优先级,那么全局行应该优先。此外,还可以有多个优先级不同的全局行。显示一些示例数据和所需结果。@CL添加了示例数据!同一个BaseID可以有多个重写吗?@CL是的,这是可能的,所以我需要优先级最小的一个value@CL我还应该补充一点,如果全局行的优先级低于非全局行的优先级,那么全局行应该优先。此外,还可能有多个优先级不同的全局行。嗯,这不会因为您在base.ID=o.BaseID上加入而错过将base加入到具有零ID的覆盖吗?嗯,这不会因为您在base.ID=o.BaseID上加入而错过将base加入到具有零ID的覆盖吗?