这个查询很有趣,但我已经到了需要帮助的地方。

我有几个表,最终的问题是:

  • 供应商“缺失”了多少个零件?

  • 和/或
  • 按供应商和类别“缺失”的零件总数是多少?

  • 缺失:供应商尚未使用 (请参阅查询 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 fiddle 中,您可以看到,因为这些部分实际上丢失了,所以在像我这样查询时,它们当然不能归因于供应商。

    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,但在第二个中,我们还获取拥有它的供应商 ID。

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

    最后,添加您的聚合和分组依据。由于左连接,如果存在 VndParts.ID,则该记录确实存在,因此 Vendor Parts 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
    

    如果这样的实际数据确实存在,那么其他类别的那些缺失的部分也会被显示出来。

    现在最后说明。您也在寻找特定的季节。我只想在 VndParts 查询中添加一个 WHERE 子句来适应它。然后更改 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'
    

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

    关于mysql - 如何使用 LEFT OUTER JOIN 按供应商识别缺失的产品?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44558439/

    10-11 20:05