数据库
首页 > 数据库> > mysql – 如何使用LEFT OUTER JOIN来识别供应商缺少的产品?

mysql – 如何使用LEFT OUTER JOIN来识别供应商缺少的产品?

作者:互联网

这个查询很有趣,但我来到了需要帮助的地方.

我有几张桌子,最终的问题是:

>供应商有多少部件“缺失”?

和/或

>按供应商和类别划分的“缺少”部件总数是多少?

缺失:供应商尚未使用(参见查询1).

请注意,零件不属于产品或供应商,因为这两者都可能根据季节而变化,而且这些零件通常会激发产品的实际含义.

基本上,每个供应商都知道哪个部分是我们试图在高层次上回答的问题,以确定哪些供应商缺少哪些类别哪些类别缺失?

现在,我确实有第一个需要工作的查询.它的作用是在指定特定供应商时按类别告诉我缺少的部分.

以下是数据库的创建脚本和工作查询的SQLfiddle:

查询1:

http://sqlfiddle.com/#!9/088e7/1

和查询:

SELECT 
    c.name AS category,
    COUNT(pt.id) AS parts,
    COUNT(CASE WHEN in_stock IS NULL THEN pt.id END) AS missing_parts
FROM 
    season AS s
LEFT OUTER JOIN 
    ( 

        SELECT 
            s.id AS season_id,
            s.type season_type,
            max(i.in_stock) AS in_stock
        FROM
            inventory AS i
            JOIN season      AS s  ON i.season_id = s.id
            JOIN product     AS p  ON i.product_id = p.id
            JOIN vendor      AS v  ON p.vendor_id = v.id
            JOIN part        AS pt ON s.part_id = pt.id

        WHERE
            v.id = 2
            AND
            s.type = 'Type A'
        GROUP BY
            1,2) AS seas   ON seas.season_id = s.id AND seas.season_type = s.type
            JOIN part      AS pt ON pt.id = s.part_id
            JOIN part_data AS pd ON pt.id = pd.part_id
            JOIN category  AS c  ON pt.category_id = c.id
    WHERE
        s.type = 'Type A'
GROUP BY
    1;

上面的作品就像一个魅力,结果如下:

| name      | parts | missing_parts |
|-----------|-------|---------------|
| category3 | 3     | 2             |
| category4 | 2     | 0             |
| category5 | 2     | 2             |
| category6 | 3     | 3             |

我的问题是当我尝试使用供应商而不是类别执行类似的查询同时删除供应商过滤器.在下面的SQL小提琴中,您可以看到,因为部件实际上是缺失的,当然不能像我一样查询时将它们归因于供应商.

http://sqlfiddle.com/#!9/088e7/2

问题2:

SELECT 
    seas.vendor AS vendor,
    COUNT(pt.id) AS parts,
    COUNT(CASE WHEN in_stock IS NULL THEN pt.id END) AS missing_parts 
FROM 
    season AS s
LEFT OUTER JOIN     
 (SELECT 
            s.id AS season_id,
            v.name AS vendor, 
            s.type season_type,
            max(i.in_stock) AS in_stock
        FROM
            inventory AS i
            JOIN season      AS s  ON i.season_id = s.id
            JOIN product     AS p  ON i.product_id = p.id
            JOIN vendor      AS v  ON p.vendor_id = v.id
            JOIN part        AS pt ON s.part_id = pt.id

        WHERE
            s.type = 'Type A'
        GROUP BY
            1,2          ) AS seas   ON seas.season_id = s.id AND seas.season_type = s.type
            JOIN part      AS pt     ON pt.id = s.part_id
            JOIN part_data AS pd     ON pt.id = pd.part_id
            JOIN category  AS c      ON pt.category_id = c.id

    AND
        s.type = 'Type A'
GROUP BY
    1;

查询2的结果:

| vendor   | parts | missing_parts |
|----------|-------|---------------|
| (null)   | 4     | 4             |
| Vendor 1 | 2     | 0             |
| Vendor 2 | 3     | 0             |
| Vendor 3 | 2     | 0             |
| Vendor 4 | 2     | 0             |
| Vendor 5 | 2     | 0             |

注意null值是有意义的,因为那些是我正在寻找的“缺失”部分,不能归因于供应商.

我想知道的是,无论如何还有一个额外的列添加了缺少的部件数?

所需输出中缺少的部分列很难准确,因为这个查询非常重要,我不知道……即使有这么少的数据.再次注意,缺少的部分没有供应商,但这是我最好的镜头.

| vendor   | parts | missing_parts |
|----------|-------|---------------|
| Vendor 1 | 2     | 1             |
| Vendor 2 | 3     | 1             |
| Vendor 3 | 2     | 3             |
| Vendor 4 | 2     | 0             |
| Vendor 5 | 2     | 2             | 

在理想的世界里,我也可以添加类别:

| category   | vendor   | parts | missing_parts |
|------------|----------|-------|---------------|
| category 1 | Vendor 1 | 2     | 1             |
| category 1 | Vendor 2 | 3     | 1             |
| category 1 | Vendor 3 | 2     | 3             |
| category 1 | Vendor 4 | 2     | 0             |
| category 1 | Vendor 5 | 2     | 2             |
| category 2 | Vendor 1 | 1     | 1             |
| category 2 | Vendor 2 | 1     | 1             |
| category 2 | Vendor 3 | 0     | 3             |
| category 2 | Vendor 4 | 2     | 0             |
| category 2 | Vendor 5 | 0     | 2             |

解决方法:

如果我理解你在寻找什么,我会首先从你最终寻找的东西开始.

不同部分和类别的列表.然后你正在寻找谁错过了什么.要做到这一点,这基本上是每个供应商的笛卡尔反对这个“主要部件/类别列表”,谁拥有/不拥有它.

SELECT DISTINCT 
      pt.id, 
      pt.category_id
   from 
      part pt

现在,考虑第二部分.特定供应商拥有的所有可能的部件和类别是什么.

SELECT DISTINCT 
      pt.id, 
      pt.category_id, 
      p.vendor_id
   FROM
      season s 
         JOIN inventory i
            ON s.id = i.season_id
            JOIN product p  
               ON i.product_id = p.id
         JOIN part pt 
            ON s.part_id = pt.id

在上面的表格中,我不需要加入类别或实际的供应商表格,因为我只关心谁拥有什么的合格ID.首先,所有可能的零件ID和类别ID,但在第二个,我们也获取拥有它的VENDOR ID.

现在,从供应商JOINED开始将各个部分组合在一起,而没有任何“ON”条件.需要连接以允许“v.id”作为语法中的较低连接,这将为我提供每个类别应用/测试的每个供应商的笛卡尔.然后,类别表连接到所有不同的部分,最后LEFT-JOINED到不同的部分查询PER VENDOR

最后,添加您的聚合和分组.由于左连接,如果存在VndParts.ID,则记录存在,因此供应商部件FOUND计数已启动.如果供应商零件ID为NULL,则缺少零件计数(因此我的总和大小/何时)将丢失.

SELECT
      v.name Vendor,
      c.name  category,
      count( PQParts.ID ) TotalAvailableParts,
      count( VndParts.ID ) VendorParts,
      sum( case when VndParts.ID IS NULL then 1 else 0 end ) MissingParts
   from
      vendor v JOIN
      category c
         JOIN 
         ( SELECT DISTINCT 
                 pt.id, 
                 pt.category_id
              from 
                 part pt ) PQParts
            ON c.id = PQParts.category_id 
            LEFT JOIN
            ( SELECT DISTINCT 
                    pt.id, 
                    pt.category_id, 
                    p.vendor_id
                 FROM
                    season s 
                       JOIN inventory i
                          ON s.id = i.season_id
                          JOIN product p  
                             ON i.product_id = p.id
                       JOIN part pt 
                          ON s.part_id = pt.id ) VndParts
               ON v.id = VndParts.vendor_id
               AND PQParts.ID = VndParts.ID
               AND PQParts.Category_ID = VndParts.Category_ID
   group by
      v.name,
      c.name

Applied against your SQL-Fiddle sample database construct

现在,即使您已经创建了类别1-6的样本数据,所有PARTS也仅使用类别3-6定义,就像我的样本数据结果一样.我无法强制获取每个样本查询不存在的数据

SELECT
      *
   from
      category c
         JOIN 
         ( SELECT DISTINCT 
                 pt.id, 
                 pt.category_id
              from 
                 part pt ) PQParts
            ON c.id = PQParts.category_id 

如果存在这样的实际数据DID,则还将显示那些缺失的其他类别.

现在最后说明.你也在寻找一个特定的季节.我只是添加一个WHERE子句来适应VndParts查询中的那个.然后更改PQParts查询以包括季节连接等

SELECT DISTINCT 
      pt.id, 
      pt.category_id
   from 
      part pt

现在,考虑第二部分.特定供应商拥有的所有可能的部件和类别是什么.

SELECT DISTINCT 
      pt.id, 
      pt.category_id
   FROM
      season s 
         JOIN part pt 
            ON s.part_id = pt.id
   WHERE
      s.type = 'Type A'

要进一步限制特定供应商,添加vendor子句很容易,因为它是外部条件下供应商“v”的基础,供应商引用第二个LEFT-JOIN也具有供应商别名可以过滤掉.

标签:outer-join,sql,mysql,join,left-join
来源: https://codeday.me/bug/20190823/1700007.html