Sql Count为相似的表集返回不同的结果,为什么?

Sql Count为相似的表集返回不同的结果,为什么?,sql,sqlite,count,firebird-3.0,Sql,Sqlite,Count,Firebird 3.0,我需要计算产品记录id与两个或多个供应商名称匹配的次数 例如,当用户输入sarsa和bobbie25时,我应该从下面的示例供应商表中获得1的值计数 这就是我所拥有的,对我来说,奇怪的是这两个方法对关键字表有效,但对供应商表无效,计数总是返回一个值0。这些表实际上是相似的,有什么问题吗 SELECT Count(distinct product_rec_id) FROM vendors INNER JOIN vendors_products ON vendors_products.ve

我需要计算产品记录id与两个或多个供应商名称匹配的次数

例如,当用户输入sarsa和bobbie25时,我应该从下面的示例供应商表中获得1的值计数

这就是我所拥有的,对我来说,奇怪的是这两个方法对关键字表有效,但对供应商表无效,计数总是返回一个值0。这些表实际上是相似的,有什么问题吗

SELECT
  Count(distinct product_rec_id)
FROM
  vendors
  INNER JOIN vendors_products ON vendors_products.vendor_rec_id = vendors.vendor_rec_id
WHERE
  (vendors.name LIKE '%sarsa%') AND
  (vendors.name LIKE '%bobbie25%')
对于Firebird 3,我将1改为True

-

-

-

vendors表中的vendor_rec_id和name字段如下所示,下面是vendors表的一个示例,其中从不存在任何空值:

vendor_rec_id  name
--------------  -----------
60              bobbie25
43              sarsa
87              johnf
vendor_rec_id  product_rec_id
--------------  --------------
43              1
60              1
43              2
87              3
vendors\u products表中的vendor\u rec\u id和product\u rec\u id看起来像是一个供应商名称可以分配给许多产品,但从来没有任何空值:

vendor_rec_id  name
--------------  -----------
60              bobbie25
43              sarsa
87              johnf
vendor_rec_id  product_rec_id
--------------  --------------
43              1
60              1
43              2
87              3

这就是我最终设法拼凑的东西。这是没有问题的

现在,当用户输入多个关键字并希望提取与输入的所有关键字匹配的记录时,我可以使用此关键字来获取记录计数和记录本身,而不需要计数*选择

我确信有更好的方法来实现这一点,但这正是我有限的SQL经验让我得到的

Select Count(*) As TRows From
(Select
  vendors_products.product_rec_id
From
  vendors_products
  Inner Join vendors On vendors_products.vendor_rec_id = vendors.vendor_rec_id
Where
  (Lower(vendors.name) Like '%sarsa%' OR
    Lower(vendors.name) Like '%bobbie25%')
Group By
  vendors_products.product_rec_id
Having
  Sum(Case
    When lower(vendors.name) Like '%sarsa%'
    Then 1
    Else 0
  End) > 0 And
  Sum(Case
    When lower(vendors.name) Like '%bobbie25%'
    Then 1
    Else 0
  End) > 0
) MyCountResults

最简单的解决方案是选择在供应商产品中有条目且具有给定供应商名称的所有产品

假设表products具有列product_id,则可以使用

为要检查的每个供应商使用exists:

with product_by_vendor as (
    select vp.product_rec_id, v.name
    from vendors v
    inner join vendors_products vp on v.vendor_rec_id = vp.vendor_rec_id
)
select count(*)
from products p
where exists (
    select * 
    from product_by_vendor 
    where product_rec_id = p.product_id
    and name like '%sarsa%')
and exists (
    select * 
    from product_by_vendor 
    where product_rec_id = p.product_id
    and name like '%bobbie25%')
with product_by_vendor as (
    select vp.product_rec_id, v.name
    from vendors v
    inner join vendors_products vp on v.vendor_rec_id = vp.vendor_rec_id
)
select count(*)
from products p
inner join product_by_vendor pv1 
    on pv1.product_rec_id = p.product_id and pv1.name like '%sarsa%'
inner join product_by_vendor pv2 
    on pv2.product_rec_id = p.product_id and pv2.name like '%bobbie25%'
要检查的每个供应商的内部联接:

with product_by_vendor as (
    select vp.product_rec_id, v.name
    from vendors v
    inner join vendors_products vp on v.vendor_rec_id = vp.vendor_rec_id
)
select count(*)
from products p
where exists (
    select * 
    from product_by_vendor 
    where product_rec_id = p.product_id
    and name like '%sarsa%')
and exists (
    select * 
    from product_by_vendor 
    where product_rec_id = p.product_id
    and name like '%bobbie25%')
with product_by_vendor as (
    select vp.product_rec_id, v.name
    from vendors v
    inner join vendors_products vp on v.vendor_rec_id = vp.vendor_rec_id
)
select count(*)
from products p
inner join product_by_vendor pv1 
    on pv1.product_rec_id = p.product_id and pv1.name like '%sarsa%'
inner join product_by_vendor pv2 
    on pv2.product_rec_id = p.product_id and pv2.name like '%bobbie25%'
使用交叉连接和ALL谓词稍微模糊一些,特定于Firebird:

with product_by_vendor as (
    select vp.product_rec_id, v.name, v.vendor_rec_id
    from vendors v
    inner join vendors_products vp on v.vendor_rec_id = vp.vendor_rec_id
),
vendors_x_products as (
    select p.product_id, v.name, v.vendor_rec_id
    from products p
    cross join vendors v
)
select count(*)
from products p
where p.product_id = all (
    select pv.product_rec_id 
    from vendors_x_products vp
    left join product_by_vendor pv
        on vp.product_id = pv.product_rec_id and vp.vendor_rec_id = pv.vendor_rec_id
    where vp.product_id = p.product_id
    and (vp.name like '%sarsa%' or vp.name like '%bobbie25%')
)

我相信可能有更简单的方法,但我现在想不起来。

在您的第一次查询中,vendor.name是否应该像“%sarsa%”和“%bobbie25%”一样同时出现?它可以是1中的任意一个,并且计数将始终为0。那么,为什么它可以毫无错误地处理关键字表呢?它总是像我期望的那样重要。表供应商的内容是什么,请更明确地说明哪些有效,哪些无效。你期望什么,为什么。如前一个问题所述,您使用countcase的整个构造。。。而凯斯。。。没有太多的意义,但我们不能建议一个替代方案,因为它真的不清楚你真正想做什么。同样在您提到的文本中,当用户进入近战和科幻时,您的示例会过滤供应商名称。请使您的问题自我一致。我编辑了我的问题。问题是,您所呈现的条件将只计算同一行中两个条件均为真的行,并且永远不会出现这种情况。为什么计数不够好?非常感谢你花时间帮助我。我会研究这些。然而,我做了几次测试,我注意到这些测试比我提出的解决方案进行了更多的抓取。最后一个是数十万。当然,它们是在索引上完成的,而不是我的解决方案,但在这种情况下,我的解决方案大约是500。这是因为我的解决方案是使用Group By并在内存中执行更多操作吗?@nDelphi最后一个解决方案在使用交叉连接的情况下,当有大量记录时可能效率不高。很难说更多的回访是好是坏,由于值将取决于页面是否被缓存在内存中,所以您可能需要多次执行查询以查看值如何变化。您可以考虑使用一个单独的SUMCASE,当LoWEnvordR.St名字像“%SARSA%”时,当LoWr.Val.Ro.s命名为“%BBBee25%”,然后1个“1”结尾=2;不过可能不会有太大的区别。