sql内部联接与存在的地方

时间:2018-06-21 15:07:00

标签: sql

我有两个表类别设备,它们具有一对多关系。

Category:
- id
- name

Device:
- id
- category_id
- brand

如果我想使用设备检索所有类别,则可以轻松地将这两个表合并在一起。

SELECT c.*, d.* FROM Category c INNER JOIN Device d ON d.category_id = c.id

问题是我也需要按brand进行过滤。

假设我有一个类别,并且该类别有3个设备。 现在,我想获得所有设备的所有类别,其中许多设备(按特定类别)中至少有一个品牌的品牌值为 foo

如果至少有一个设备与此品牌相匹配,那么我需要退回所有设备。如果没有匹配项,那么我需要返回空结果(没有类别,也没有设备)。

我尝试了以下查询,但似乎无法正常工作。

SELECT c.*, d.*
FROM Category c
    INNER JOIN Device d ON d.category_id = c.id
WHERE EXISTS (SELECT * FROM Device d WHERE brand = 'foo')

问题是应该为每个类别执行此WHERE EXISTS

有帮助吗?

3 个答案:

答案 0 :(得分:1)

您需要correlation

select c.*, d.*
from Category c inner join 
     Device d
     on d.category_id = c.id
where exists (select 1 
              from Device d1 
              where d1.category_id = c.id and d1.brand = 'foo'
             );

答案 1 :(得分:0)

您可以多次加入一个表;一个过滤,一个获取数据

SELECT DISTINCT 
    cat.*
    , devData.*
FROM Device AS devFilter
    INNER JOIN Category AS cat
         ON devFilter.category_id = cat.id
    LEFT JOIN Device AS devData
         ON devData.category_id = cat.id
WHERE devFilter.Brand = 'foo'

使用少量到中等的数据集就可以了。如果DISTINCT降低了性能,那么我建议嵌套,以便从devFilter仅返回1个设备,然后再次加入。

SELECT 
    cat.*
    , dev.*
FROM
(
    SELECT DISTINCT devFilter.category_id
    FROM Device AS devFilter
    WHERE devFilter.Brand = 'foo'
) AS categoriesWithBrand
    LEFT JOIN Device AS dev
         ON dev.category_id = categoriesWithBrand.category_id
    LEFT JOIN Category AS cat
         ON cat.id = categoriesWithBrand.category_id

答案 2 :(得分:0)

您可以尝试CTE。

;with CategoryBrand as
(
   select distinct c.id as category_id, brand
     from category c
    inner join device d on c.id = d.category_id
)
select c.*, d.*
  from CategoryBrand cb
 inner join Category c on c.id = cb.category_id
                      and cb.Brand = 'foo'
 inner join Device d on c.id = d.category_id

CTE CategoryBrand建立了类别到品牌的映射。

下面的SQL仅获得类别,这些类别映射到所需的品牌,然后从该类别连接到设备。