3

我正在尝试将“简化”的 sql 查询转换为可用于 XnViews 数据库的有效 SQLite 查询,这意味着数据库布局对于我正在尝试做的事情来说充其量是次优的,而且我对此无能为力。

例如“(cat_10 and cat_12) and (cat_5 or cat_7)”。

这应该用于表“t3”,该表具有字段“if”(fileID)和“ic”(categoryID)。

条目如下所示:

if, ic
7, 10
7, 12
7, 4
9, 10
9, 12
9, 5
10, 10
10, 12
10, 7

上面的简化查询应该只选择文件 9 和 10,因为 7 确实具有所需的类别 10 和 12,但既没有 5 也没有 7。

现在的实际问题是构建一个查询语句的地狱,因为我已经花了几个小时来简单地在两个类别之间进行 AND 工作。

SELECT if FROM t3 WHERE ic IN (10, 12) GROUP BY if HAVING count(if) = 2

这给了我所有包含类别 10 和 12 的文件 ID,但我不知道我应该如何将其与剩余的“和(cat_5 或 cat_7)”结合起来。

当我计划这些简化的 sql 语句(由 html 和 js 中的 click-it-together-builder 生成)时,我打算简单地将“cat_5”替换为“t3.ic = 5”,其余部分保持原样。

当然,我没有预见到它不能作为一个整体检查条目的地方,并且不能有 ic = 5 和 ic = 7。这几乎破坏了一切。

所以我想知道是否有人知道我如何将这些简单的查询翻译成实际工作的查询,请记住它可能不限于( x 和 y )对。

编辑:我想出了如何做我给出的例子,我认为至少:

SELECT if FROM t3 WHERE ic IN (10, 12) GROUP BY if HAVING count(if) = 2
INTERSECT 
SELECT if FROM t3 WHERE ic IN (5, 7) GROUP BY if

但现在的主要问题是以正确的顺序解决 ( ) 。

编辑 2:我想我正在尝试使用 group_concat() 将类别分组到一个字段中,然后我应该能够简单地对猫 LIKE "" AND 这将是我可以轻松拼凑在一起的小块,然后只是括号它应该可以工作。突出“应该”。

4

4 回答 4

2

您的原始查询不符合预期。WHERE ic IN (10, 12) GROUP BY if HAVING count(if) = 2即使你ic在 10 和 10 中有 s 但根本没有 12,也会产生正确的结果。这与您对所需内容的文字描述背道而驰。这是需要内部查询来获取 12 和 10 的结果的地方。您可以在我在下面发布的小提琴链接中测试您的查询是否失败。

有点棘手,但这就是我直接解释它的方式。

SELECT DISTINCT ifc
FROM   t3
WHERE  ifc IN (
               SELECT   ifc
               FROM     t3 
               WHERE    ic = 10  
               GROUP BY ifc
               HAVING   COUNT(*) > 0             

               INTERSECT

               SELECT   ifc
               FROM     t3 
               WHERE    ic = 12
               GROUP BY ifc
               HAVING   COUNT(*) > 0
              )            
AND ic IN (5, 7)

试试小提琴

我没有带来任何优化,你可以试试你的。小提琴链接是 Postgres 的,但这应该可以工作(没有让 SQLite 在我的浏览器中工作:()

编辑: CL。指出了一个有趣的事情,即不必HAVING在内部查询中包含子句,这是真的。我用 SQL 术语解释 OP 的要求,目的是在不考虑任何优化的情况下使事情变得清晰。

这是一个更好看的查询:

SELECT DISTINCT ifc
FROM   t3
WHERE  ifc IN (
               SELECT   ifc
               FROM     t3 
               WHERE    ic = 10            

               INTERSECT

               SELECT   ifc
               FROM     t3 
               WHERE    ic = 12
              )            
AND ic IN (5, 7)
于 2012-11-06T06:45:25.757 回答
0

好的,我出人意料地按照我最初的计划工作了。

SELECT Folders.Pathname || Images.Filename AS File FROM Images
JOIN Folders ON Images.FolderID = Folders.FolderID
LEFT JOIN (
    SELECT f, Cats, t4.if AS Tagged FROM t2
    JOIN (
        SELECT if, ' ' || group_concat(ic,' ') || ' ' AS Cats FROM t3 GROUP BY if
    ) st3 ON t2.i = st3.if
    LEFT JOIN t4 ON t2.i = t4.if
) st2 ON File = st2.f
$selectWhereImage $sqlqry
ORDER BY ModifiedDate $order LIMIT $offset, $limit

我知道这是一个非常糟糕的查询,但它结合了我要查找的所有内容(类别 ID、是否标记、评级、颜色),可按日期排序,结果是完整的文件路径。

这可能是一种可怕的方法,但如果有人找到一种更好的工作方式,我可以简单地替换像“cat_5”这样的占位符,同时保持其余部分保持原样,需要括号和运算符,那么我会全神贯注:D

哦,$selectWhereImage 只包含一个更长的 WHERE,它限制 File 以图像格式结尾, $sqlqry 是上面的 refitte 东西,cat_5只会变成cat LIKE '% 5 %',因为猫我可以匹配任何数字而不会在“10”中找到“1”,因为“1”不在“10”中:D

于 2012-11-07T17:42:50.727 回答
0

如果您必须像以前那样使用相交,则应该更改错误的上层查询。既然你必须确保每个if人都有一个 10 和 12,ic那么如果没有两个单独的查询,你就无法逃脱。就像是:

SELECT ifc
FROM   t3
WHERE  ifc IN (
               SELECT   ifc
               FROM     t3 
               WHERE    ic = 10
              ) 
   AND ifc IN (
               SELECT   ifc
               FROM     t3 
               WHERE    ic = 12
              )

INTERSECT

SELECT ifc FROM t3 WHERE ic IN (5, 7)

INTERSECT在此处处理组,因此您不必显式添加,但这不会像我的其他查询那样有效。如果您必须摆脱子查询,您可以使用JOIN

SELECT DISTINCT t.ifc
FROM   t3 AS t
JOIN   t3 AS v ON v.ifc = t.ifc
JOIN   t3 AS p ON p.ifc = t.ifc
WHERE  v.ic = 10 AND p.ic = 12 AND t.ic IN (5, 7)

第二个的优点是它可以在不知道INTERSECTMySQL 的数据库上工作。

于 2012-11-08T20:31:18.053 回答
0

A hackish approach which would be simpler and I believe faster is

SELECT DISTINCT ifc
FROM   t3
WHERE  ifc IN (
               SELECT   ifc
               FROM     t3 
               WHERE    ic = 10
              ) 
   AND ifc IN (
               SELECT   ifc
               FROM     t3 
               WHERE    ic = 12
              )               
AND ic IN (5, 7)
于 2012-11-08T20:15:07.607 回答