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

时间:2018-03-30 13:58:01

标签: sql sqlite count firebird-3.0

我需要计算product_rec_id匹配,分配,两个或多个供应商名称的次数。

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

这就是我所拥有的,而对我来说奇怪的是,这两个方法对关键字的表有效,但对供应商的表无效,Count总是返回值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,我将Then 1更改为Then True

SELECT
  Count((CASE
    WHEN vendors.name LIKE '%sarsa%'
    THEN 1
  END) AND (CASE
    WHEN vendors.name LIKE '%bobbie25%'
    THEN 1
  END)) AS TRows
FROM
  vendors
  INNER JOIN vendors_products ON vendors_products.vendor_rec_id = vendors.vendor_rec_id
WHERE
  (vendors.name LIKE '%sarsa%' OR
    vendors.name LIKE '%bobbie25%')

-

CREATE TABLE vendors (
    vendor_rec_id     INTEGER       PRIMARY KEY NOT NULL,
    company_broker_id INTEGER       NOT NULL,
    name              VARCHAR (50)  NOT NULL,
    vendor_id         VARCHAR (50),
    store_url         VARCHAR (255),
    website_url       VARCHAR (255) 
);

CREATE TABLE vendors_products (
    product_rec_id INTEGER NOT NULL,
    vendor_rec_id  INTEGER
);

-

vendors' table data:
        60 2 bobbie25 73658 http://www.somewebsite.com/ http://www.somewebsite.com/
        43 2 sarsa    61688 http://www.somewebsite.com/ http://www.somewebsite.com/

-

CREATE TABLE keywords (
    keyword_rec_id INTEGER      PRIMARY KEYNOT NULL,
    keyword        VARCHAR (50) NOT NULL UNIQUE,
    chart          INTEGER      NOT NULL
                                DEFAULT 0
);
CREATE TABLE keywords_products (
    keyword_rec_id INTEGER NOT NULL,
    product_rec_id INTEGER
);

供应商表中的vendor_rec_id和名称字段如下所示,这是供应商表的示例(从不存在任何空值):

vendor_rec_id  name
--------------  -----------
60              bobbie25
43              sarsa
87              johnf

vendors_products 表中的vendor_rec_id和product_rec_id看起来像这样(一个供应商名称可以分配给许多产品)(从来没有任何空值):

vendor_rec_id  product_rec_id
--------------  --------------
43              1
60              1
43              2
87              3

2 个答案:

答案 0 :(得分:1)

这是我最终设法组合起来的。这没有问题。

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

我确信有更好的方法可以完成这项工作,但这是我对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

答案 1 :(得分:0)

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

假设某个表products的列product_id,您可以使用

执行此操作
  1. 对要检查的每个供应商使用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%')
    
  2. 您要检查的每个供应商的inner join

    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%'
    
  3. 使用cross joinALL谓词稍微模糊一点(以及特定于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%')
    )
    
  4. 我确信可能有一种更简单的方法,但我现在无法想到它。