【问题标题】:SQL query : How to change integer to booleanSQL查询:如何将整数更改为布尔值
【发布时间】:2018-07-24 09:58:53
【问题描述】:

我正在使用 Firebird 2.5.8 和 Delphi 10.2.3,我想用查询填充 DBGrid:

SELECT c.ID, l.ID,
(
SELECT COUNT(pl.ID)
FROM Tbl_ProtocolLicense AS pl
WHERE (pl.ReferenceId=l.ID)
) AS ReferenceCount

FROM  Tbl_License AS l, tbl_client AS c
WHERE l.ClientId=c.Id;

如何将值 (ReferenceCount > 0) 作为布尔值或 (0/1) 添加到该查询?

【问题讨论】:

  • @Victoria:我在这里问之前尝试过,但我没有让它与 Select 结构中的 Select 一起使用。我总是遇到 SQL 错误
  • 火鸟版本是什么?布尔值仅在 FB3 中引入(并且可能仅在方言 3 中)
  • 另一种方法是在客户端执行此操作。
  • @Victoria CASE???谁需要案例???? Select ..... MaxValue( MinValue( ReferenceCount, 1), 0) .... :-P

标签: sql delphi firebird


【解决方案1】:

为什么还要使用会为每一行一次又一次地重新计算的相关查询?

第一个查询实际上不起作用。太仓促了。

SELECT 
  c.ID,
  l.ID, 
  IIF( r.CNT > 0, 1, 0 )
FROM Tbl_License AS l
  JOIN tbl_client AS c ON l.ClientId=c.Id
  JOIN (
    SELECT COUNT(*) as CNT, ReferenceId as ID
    FROM Tbl_ProtocolLicense 
    GROUP BY 2
        ) as r ON r.ID = l.ID

注意:这假定Tbl_ProtocolLicense.ID 列永远不是NULL


UPD。我在http://stackoverflow.com/a/51159126/976391 做了一些关于 COUNT 和其他聚合的讲座 - 但在这里我自己错过了。

 SELECT COUNT(*) as CNT, ReferenceId as ID
        FROM Tbl_ProtocolLicense 
        GROUP BY 2

运行查询并查看结果。有什么可疑的地方吗?

这个查询只返回确实存在的行,而不是那些不存在的。

中间分组查询不会有一行,其中 count=0 ! 因此,整个基于 Inner Join 的查询也不会有它们!

我们应该做的是使用外连接,即使在另一个表中没有匹配的行时也可以让行存在。阅读:https://en.wikipedia.org/wiki/Join_(SQL)

SELECT 
  c.ID,
  l.ID, 
  IIF( r.CNT is not NULL, 1, 0 )
FROM Tbl_License AS l
  JOIN tbl_client AS c ON l.ClientId=c.Id
  LEFT JOIN (
    SELECT COUNT(*) as CNT, ReferenceId as ID
    FROM Tbl_ProtocolLicense 
    GROUP BY 2
        ) as r ON r.ID = l.ID

将输出与第一个查询进行比较,看看有什么不同。


UPD 2。但即使这样也不够好,可能。这里的问题是“你说你想要你实际上并不想要的东西”。

当您真的不关心计数时,您要求 Firebird 计数所有行。您所关心的只是“是否至少有一排或根本没有”。如果只有一行 - 你不在乎是否会有 10 或 100 或 1000 更多。因此,当您不想计数对象时,实际计数对象是一项白费力气的额外工作。

这在 Interbase/Firebird 系列中尤其浪费,在表格中计数会触发 garbage collection 并减慢工作速度。但即使在纯 Delphi 中也是如此 - 如果您对找到第一个适合的元素感到满意,您不想遍历所有数组。

然后我们可以回到相关的子查询。

SELECT 
  c.ID,
  l.ID,
  IIF( EXISTS ( 
         SELECT * FROM Tbl_ProtocolLicense AS pl
         WHERE pl.ReferenceId=l.ID 
       ), 1, 0 )   
FROM  Tbl_License AS l, tbl_client AS c
WHERE l.ClientId=c.Id;
  • c.s.q. 苦涩的一面。是不是它正在为每个结果行一次又一次地运行
  • 计算分组总计数的苦涩的一面是您实际上不需要该数据,也不需要确切的计数。

哪个更糟?谁知道。根据真实数据和真实表/索引 - 可能存在一种或另一种方法会更快的情况。人类不会注意到小数据的差异。这是关于“扩大”到成千上万的真实数据的问题,差异会在哪里显示出来。


UPD 3. 我们可以同时采用这两种方法吗?我希望我们可以。诀窍是 - 问确切我们需要什么,而不再。我们可以要求 Firebird 列出我们在表中的所有 ID 而不实际计算它们吗?是的,有。

 SELECT DISTINCT ReferenceId FROM Tbl_ProtocolLicense  

运行查询并查看结果!

注意,它仍然不会列出不在表中的 ID。明显的?好吧,我在第一种方法中错过了它,然后两个支持我的人也错过了。愚蠢的错误是最难发现的,因为你无法相信这种愚蠢。

所以,现在我们必须插入它而不是“计数”第二次尝试的查询。

SELECT 
  c.ID,
  l.ID, 
  IIF( r.ReferenceId is NULL, 0, 1 )
FROM Tbl_License AS l
  JOIN tbl_client AS c ON l.ClientId=c.Id
  LEFT JOIN (
    SELECT DISTINCT ReferenceId 
    FROM Tbl_ProtocolLicense 
      ) as r ON r.ReferenceId = l.ID

UPD。 4 最后一招。如果我是正确的,这个查询将得到与上面完全相同的结果,而不使用 IIF/CASE。尝试并比较。如果结果相同,那么请尝试了解其工作原理和方式,以及需要对数据进行哪些额外假设。

SELECT 
  c.ID,
  l.ID, 
  COUNT( r.ReferenceId )
FROM Tbl_License AS l
  JOIN tbl_client AS c ON l.ClientId=c.Id
  LEFT JOIN (
    SELECT DISTINCT ReferenceId 
    FROM Tbl_ProtocolLicense 
      ) as r ON r.ReferenceId = l.ID
GROUP BY c.ID, l.ID

这个查询并不比 Upd.3 好,它只是一个思考然后更好地理解 SQL 的探索。


现在做一些工作来实际检查和比较结果,因为盲目相信互联网上的陌生人是不好的。即使那个人没有恶意,他也会犯愚蠢的错误。

无论您从 Internet 论坛上看到什么,都只是“示例”和“想法演示”,您始终有责任了解和检查该示例。也许会拒绝它。


阅读和理解:

此外,阅读一些关于一般 SQL 的好书,比如 Martin Gruber 的书,对您真的很有用

【讨论】:

  • 很高兴听到。但是,确实,您必须阅读一些关于数据库和 SQL 的好书,以及更多关于概念和方法的书籍,而不是技术专家。我可以建议你一本关于 Delphi 3/5 的概述+速成课程书(旧版本无关紧要,因为它提供的 BASICS 在任何地方都是相同的)-如果它不是俄语的:-D
  • 其实这样不行。您在第三列中没有零的单行.....
  • 那我测试太快了。当我测试时,我的数据库中只有带有协议的客户端。所以计数总是> 0。后来我使用了您的 Maxvalue 示例,因为我了解它的作用。这是正确的。但我还没有时间在这里理解你的构造。休息几周后,我会试着理解你写的东西。我对 SQL 的问题是我继承了一个非常混乱的项目(使用 SQL),我每年的投资不能超过 2-3 周,因为它只是一个内部项目。
  • 原始示例中的 GROUP BY 2 是做什么的?在示例中,我没有看到任何数字。所以昨天2让我头疼。我一点头绪都没有。所以我停止了尝试。
  • 只是列的编号,而不是复制名称。但是,为什么要猜???我给了你大量的文档链接,为什么不直接阅读呢。甚至是维基百科。看,你确实需要 SQL 教程..." • 分组为 firebirdsql.org/file/documentation/reference_manuals/…"
猜你喜欢
  • 2010-12-16
  • 1970-01-01
  • 2021-07-25
  • 2014-12-17
  • 1970-01-01
  • 1970-01-01
  • 2015-08-29
  • 2013-02-09
  • 1970-01-01
相关资源
最近更新 更多