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