【问题标题】:sql - Get the Minimum Value of 2 subqueriessql - 获取 2 个子查询的最小值
【发布时间】:2020-03-07 03:54:52
【问题描述】:

我有一个包含 5 个子查询的查询。我需要它只有 4 个子查询,因为其中两个应该只有一个结果。问题是我不知道如何维护查询结构并获取这些子查询中 2 的 MIN 值。这是我的查询:

Select Artigo, Descricao, sum(Stock) as Stock, Sum(QuantidadeEmEncomendasPendentes) as QuantidadeEmEncomendasPendentes, Sum(Stock) - Sum(QuantidadeEmEncomendasPendentes) As StockTotal
From (

    Select A1.Artigo as Artigo, A1.Descricao as Descricao, sum(AA.StkActual) as Stock, 0 as QuantidadeEmEncomendasPendentes, 'Artigo Stock' As Id
    From Artigo A1
        Inner Join ArtigoArmazem AA On AA.Artigo = A1.Artigo And (AA.Armazem IN ('A1','A5','A7','A8','A9'))
        and A1.CDU_DisponivelOnline = 1
    Group By A1.Artigo, A1.Descricao

    Union

    Select A1.Artigo as Artigo, A1.Descricao as Descricao, 0 as Stock, Sum(LD.Quantidade - LDS.QuantTrans) as QuantidadeEmEncomendasPendentes, 'Artigo Encomenda' As Id
    From Artigo A1
        Inner Join LinhasDoc LD On LD.Artigo = A1.Artigo And Year(LD.Data) >= 2018 And LD.Quantidade Is Not Null And LD.Quantidade > 0
        Inner Join LinhasDocStatus LDS On LDS.IdLinhasDoc = LD.Id  And LDS.Fechado = 0 And LDS.Quantidade > LDS.QuantTrans
        Inner Join CabecDocStatus CDS On CDS.IdCabecDoc = LD.IdCabecDoc And CDS.Fechado = 0 And CDS.Estado = 'P'
        Inner Join CabecDoc CD On CD.Id = LD.IdCabecDoc And CD.TipoDoc = 'NET' And CD.Serie = 'SITE'
        and A1.CDU_DisponivelOnline = 1
    Group By A1.Artigo, A1.Descricao

    Union

    select
        A1.Artigo as Artigo, A1.Descricao as Descricao, FLOOR(MIN(CASE WHEN A2.familia = 39 THEN AA.StkActual / 2 ELSE AA.StkActual END)) as Stock, 0 as QuantidadeEmEncomendasPendentes, 'Componente Stock' As Id
    from
        Artigo A1
        join ComponentesArtigos CA On CA.ArtigoComposto = A1.Artigo
        join Artigo A2 On A2.Artigo = CA.Componente And (A2.Familia IN (37,38,39,45))
        join ArtigoArmazem AA ON AA.Artigo = A2.Artigo And (AA.Armazem IN ('A7'))
        and A1.CDU_DisponivelOnline = 1
    group by
        A1.Artigo,
        A1.Descricao

    Union

    select
        A1.Artigo as Artigo, A1.Descricao as Descricao, (coalesce(MIN(
            CASE
                when AA.Armazem = 'A7' then 
                    CASE WHEN A2.Familia = 98 THEN AA.StkActual END
                else
                    null
            end
        ), MIN(
            CASE
                when AA.Armazem = 'A8' then 
                    CASE WHEN A2.Familia = 98 THEN AA.StkActual END
                else
                    null
            end
        ), MIN(
            CASE
                when AA.Armazem = 'A9' then 
                    CASE WHEN A2.Familia = 98 THEN AA.StkActual END
                else
                    null
            end
        ))) as Stock, 0 as QuantidadeEmEncomendasPendentes, 'Componente Stock' As Id
    from
        Artigo A1
        join ComponentesArtigos CA On CA.ArtigoComposto = A1.Artigo
        join Artigo A2 On A2.Artigo = CA.Componente And (A2.Familia IN (98))
        join ArtigoArmazem AA ON AA.Artigo = A2.Artigo And (AA.Armazem IN ('A7', 'A8', 'A9'))
        and A1.CDU_DisponivelOnline = 1
    group by
        A1.Artigo,
        A1.Descricao

    Union

    Select A1.Artigo as Artigo, A1.Descricao as Descricao, 0 as Stock, Sum(LD.Quantidade - LDS.QuantTrans) as QuantidadeEmEncomendasPendentes, 'Componente Encomenda' As Id
    From Artigo A1
        Inner Join ComponentesArtigos CA On CA.ArtigoComposto = A1.Artigo
        Inner Join Artigo A2 On A2.Artigo = CA.Componente And (A2.Familia IN (37,38,39,45,98))
        Inner Join LinhasDoc LD On LD.Artigo = A2.Artigo And Year(LD.Data) >= 2018 And LD.Quantidade Is Not Null And LD.Quantidade > 0
        Inner Join LinhasDocStatus LDS On LDS.IdLinhasDoc = LD.Id  And LDS.Fechado = 0 And LDS.Quantidade > LDS.QuantTrans
        Inner Join CabecDocStatus CDS On CDS.IdCabecDoc = LD.IdCabecDoc And CDS.Fechado = 0 And CDS.Estado = 'P' And LDS.IdLinhasDoc Is Not Null 
        Inner Join CabecDoc CD On CD.Id = LD.IdCabecDoc And CD.TipoDoc = 'NET' And CD.Serie = 'SITE' And CDS.IdCabecDoc Is Not Null
        and A1.CDU_DisponivelOnline = 1
    Group By A1.Artigo, A1.Descricao

) As Result
Group by Artigo, Descricao
order by Descricao

我需要获取第 3 和第 4 个子查询的最小值,而不是将它们都添加到主查询的 SUM(Stock) 中。我怎样才能做到这一点?我需要维护查询结构.. 我需要这些查询(第 3 次和第 4 次)结果中的 MIN:

select
        A1.Artigo as Artigo, A1.Descricao as Descricao, FLOOR(MIN(CASE WHEN A2.familia = 39 THEN AA.StkActual / 2 ELSE AA.StkActual END)) as Stock, 0 as QuantidadeEmEncomendasPendentes, 'Componente Stock' As Id
    from
        Artigo A1
        join ComponentesArtigos CA On CA.ArtigoComposto = A1.Artigo
        join Artigo A2 On A2.Artigo = CA.Componente And (A2.Familia IN (37,38,39,45))
        join ArtigoArmazem AA ON AA.Artigo = A2.Artigo And (AA.Armazem IN ('A7'))
        and A1.CDU_DisponivelOnline = 1
    group by
        A1.Artigo,
        A1.Descricao

    Union

    select
        A1.Artigo as Artigo, A1.Descricao as Descricao, (coalesce(MIN(
            CASE
                when AA.Armazem = 'A7' then 
                    CASE WHEN A2.Familia = 98 THEN AA.StkActual END
                else
                    null
            end
        ), MIN(
            CASE
                when AA.Armazem = 'A8' then 
                    CASE WHEN A2.Familia = 98 THEN AA.StkActual END
                else
                    null
            end
        ), MIN(
            CASE
                when AA.Armazem = 'A9' then 
                    CASE WHEN A2.Familia = 98 THEN AA.StkActual END
                else
                    null
            end
        ))) as Stock, 0 as QuantidadeEmEncomendasPendentes, 'Componente Stock' As Id
    from
        Artigo A1
        join ComponentesArtigos CA On CA.ArtigoComposto = A1.Artigo
        join Artigo A2 On A2.Artigo = CA.Componente And (A2.Familia IN (98))
        join ArtigoArmazem AA ON AA.Artigo = A2.Artigo And (AA.Armazem IN ('A7', 'A8', 'A9'))
        and A1.CDU_DisponivelOnline = 1
    group by
        A1.Artigo,
        A1.Descricao

【问题讨论】:

  • 只需先将它们合并在一起,找到最小值,然后将结果与其他子查询合并。
  • @EzLo 怎么样?几天来我一直在尝试这样做,但这似乎是不可能的。我无法更改查询结构,因为它需要从“不同角度”计算所有股票。我很讨厌 sql

标签: sql sql-server subquery min


【解决方案1】:

考虑将子查询变成多个CTEs,然后在UNION查询中根据对应的StockStock3Stock4添加列聚合MIN 值,填写NULLs 用于其他查询:

WITH first_agg AS (
    SELECT A1.Artigo AS Artigo, A1.Descricao AS Descricao, 
          SUM(AA.StkActual) AS Stock, 
          0 AS QuantidadeEmEncomendasPendentes, 
          'Artigo Stock' AS Id
    FROM Artigo A1
    INNER JOIN ArtigoArmazem AA 
        ON AA.Artigo = A1.Artigo 
        AND (AA.Armazem IN ('A1','A5','A7','A8','A9'))
        AND A1.CDU_DisponivelOnline = 1
    GROUP BY A1.Artigo, A1.Descricao
), 

second_agg AS (
    SELECT A1.Artigo AS Artigo, A1.Descricao AS Descricao, 
           0 AS Stock, 
           SUM(LD.Quantidade - LDS.QuantTrans) AS QuantidadeEmEncomendasPendentes, 
           'Artigo Encomenda' AS Id
    FROM Artigo A1
        INNER JOIN LinhasDoc LD 
             ON LD.Artigo = A1.Artigo AND Year(LD.Data) >= 2018 
             AND LD.Quantidade Is Not Null AND LD.Quantidade > 0
        INNER JOIN LinhasDocStatus LDS 
             ON LDS.IdLinhasDoc = LD.Id  
             AND LDS.Fechado = 0 AND LDS.Quantidade > LDS.QuantTrans
        INNER JOIN CabecDocStatus CDS 
             ON CDS.IdCabecDoc = LD.IdCabecDoc 
             AND CDS.Fechado = 0 AND CDS.Estado = 'P'
        INNER JOIN CabecDoc CD 
             ON CD.Id = LD.IdCabecDoc 
             AND CD.TipoDoc = 'NET' AND CD.Serie = 'SITE'
        AND A1.CDU_DisponivelOnline = 1
    GROUP BY A1.Artigo, A1.Descricao
),

third_agg AS (    
    SELECT
        A1.Artigo AS Artigo, A1.Descricao AS Descricao, 
        FLOOR(MIN(CASE 
                       WHEN A2.familia = 39 
                       THEN AA.StkActual / 2 
                       ELSE AA.StkActual 
                  END)) AS Stock, 
        0 AS QuantidadeEmEncomendasPendentes, 
        'Componente Stock' AS Id
    FROM
        Artigo A1
        INNER JOIN ComponentesArtigos CA 
              ON CA.ArtigoComposto = A1.Artigo
        INNER JOIN Artigo A2 
              ON A2.Artigo = CA.Componente AND (A2.Familia IN (37,38,39,45))
        INNER JOIN ArtigoArmazem AA 
              ON AA.Artigo = A2.Artigo AND (AA.Armazem IN ('A7'))
        AND A1.CDU_DisponivelOnline = 1
    GROUP BY
        A1.Artigo,
        A1.Descricao
),

fourth_agg AS (
    SELECT A1.Artigo AS Artigo, A1.Descricao AS Descricao, 
            (COALESCE(MIN(
                CASE
                    WHEN AA.Armazem = 'A7' 
                    THEN CASE WHEN A2.Familia = 98 THEN AA.StkActual END
                    ELSE NULL
                END
            ), MIN(
                CASE
                    WHEN AA.Armazem = 'A8' 
                    THEN CASE WHEN A2.Familia = 98 THEN AA.StkActual END
                    ELSE NULL
                END
            ), MIN(
                CASE
                    WHEN AA.Armazem = 'A9' 
                    THEN CASE WHEN A2.Familia = 98 THEN AA.StkActual END
                    ELSE NULL
                END
            ))) AS Stock, 
            0 AS QuantidadeEmEncomendasPendentes, 
            'Componente Stock' AS Id
    FROM
        Artigo A1
        INNER JOIN ComponentesArtigos CA 
              ON CA.ArtigoComposto = A1.Artigo
        INNER JOIN Artigo A2 
              ON A2.Artigo = CA.Componente AND (A2.Familia IN (98))
        INNER JOIN ArtigoArmazem AA 
              ON AA.Artigo = A2.Artigo AND (AA.Armazem IN ('A7', 'A8', 'A9'))
              AND A1.CDU_DisponivelOnline = 1
    GROUP BY
        A1.Artigo,
        A1.Descricao
),

fifth_agg AS (
    SELECT A1.Artigo AS Artigo, A1.Descricao AS Descricao, 
           0 AS Stock, 
           SUM(LD.Quantidade - LDS.QuantTrans) AS QuantidadeEmEncomendasPendentes, 
           'Componente Encomenda' AS Id
    FROM Artigo A1
        INNER JOIN ComponentesArtigos CA 
              ON CA.ArtigoComposto = A1.Artigo
        INNER JOIN Artigo A2 
              ON A2.Artigo = CA.Componente AND (A2.Familia IN (37,38,39,45,98))
        INNER JOIN LinhasDoc LD 
              ON LD.Artigo = A2.Artigo AND Year(LD.Data) >= 2018 
              AND LD.Quantidade Is Not Null AND LD.Quantidade > 0
        INNER JOIN LinhasDocStatus LDS 
              ON LDS.IdLinhasDoc = LD.Id  
              AND LDS.Fechado = 0 AND LDS.Quantidade > LDS.QuantTrans
        INNER JOIN CabecDocStatus CDS 
              ON CDS.IdCabecDoc = LD.IdCabecDoc AND CDS.Fechado = 0 
              AND CDS.Estado = 'P' AND LDS.IdLinhasDoc Is Not Null 
        INNER JOIN CabecDoc CD 
              ON CD.Id = LD.IdCabecDoc AND CD.TipoDoc = 'NET' 
              AND CD.Serie = 'SITE' AND CDS.IdCabecDoc Is Not Null
        AND A1.CDU_DisponivelOnline = 1
    GROUP BY A1.Artigo, A1.Descricao
)


SELECT Artigo, Descricao, 
       SUM(Stock) AS Stock, 
       SUM(QuantidadeEmEncomendasPendentes) AS QuantidadeEmEncomendasPendentes, 
       SUM(Stock) - SUM(QuantidadeEmEncomendasPendentes) AS StockTotal,
       MIN(Stock3) AS MIN_Stock3,
       MIN(Stock4) AS Min_Stock4

FROM (    
       SELECT Artigo, Descricao, Stock, NULL AS Stock3, NULL AS Stock4, 
              QuantidadeEmEncomendasPendentes, ID 
       FROM first_agg

       UNION 

       SELECT Artigo, Descricao, Stock, NULL AS Stock3, NULL AS Stock4, 
              QuantidadeEmEncomendasPendentes, ID 
       FROM second_agg

       UNION

       SELECT Artigo, Descricao, Stock, Stock AS Stock3, NULL AS Stock4, 
              QuantidadeEmEncomendasPendentes, ID 
       FROM third_agg

       UNION

       SELECT Artigo, Descricao, Stock, NULL AS Stock3, Stock AS Stock4, 
              QuantidadeEmEncomendasPendentes, ID 
       FROM fourth_agg

       UNION

       SELECT Artigo, Descricao, Stock, NULL AS Stock3, NULL AS Stock4, 
              QuantidadeEmEncomendasPendentes, ID 
       FROM fifth_agg      

) AS Result
GROUP BY Artigo, Descricao
ORDER BY Descricao

【讨论】:

  • 不知道那些 CTE。谢谢 Parfait,你没有给我我需要的东西,但感谢你的帮助,我终于得到了解决方案
  • 听起来不错!是的,与子查询相比,CTE 允许您定义一次结果集并在任何地方重用,即使在其他 CTE 内部也是如此。
【解决方案2】:

希望,我正确理解了您的问题。

将以下查询用于您的第三个和第四个查询。

SELECT Artigo ,Descricao , Stock , QuantidadeEmEncomendasPendentes , Id
FROM
(
SELECT Artigo ,Descricao , Stock , QuantidadeEmEncomendasPendentes , Id ,    ROW_NUMBER() OVER(ORDER BY Stock ASC) RN
FROM
(
select
        A1.Artigo as Artigo, A1.Descricao as Descricao, FLOOR(MIN(CASE WHEN A2.familia = 39 THEN AA.StkActual / 2 ELSE AA.StkActual END)) as Stock, 0 as QuantidadeEmEncomendasPendentes, 'Componente Stock' As Id
    from
        Artigo A1
        join ComponentesArtigos CA On CA.ArtigoComposto = A1.Artigo
        join Artigo A2 On A2.Artigo = CA.Componente And (A2.Familia IN (37,38,39,45))
        join ArtigoArmazem AA ON AA.Artigo = A2.Artigo And (AA.Armazem IN ('A7'))
        and A1.CDU_DisponivelOnline = 1
    group by
        A1.Artigo,
        A1.Descricao

    Union

    select
        A1.Artigo as Artigo, A1.Descricao as Descricao, (coalesce(MIN(
            CASE
                when AA.Armazem = 'A7' then 
                    CASE WHEN A2.Familia = 98 THEN AA.StkActual END
                else
                    null
            end
        ), MIN(
            CASE
                when AA.Armazem = 'A8' then 
                    CASE WHEN A2.Familia = 98 THEN AA.StkActual END
                else
                    null
            end
        ), MIN(
            CASE
                when AA.Armazem = 'A9' then 
                    CASE WHEN A2.Familia = 98 THEN AA.StkActual END
                else
                    null
            end
        ))) as Stock, 0 as QuantidadeEmEncomendasPendentes, 'Componente Stock' As Id
    from
        Artigo A1
        join ComponentesArtigos CA On CA.ArtigoComposto = A1.Artigo
        join Artigo A2 On A2.Artigo = CA.Componente And (A2.Familia IN (98))
        join ArtigoArmazem AA ON AA.Artigo = A2.Artigo And (AA.Armazem IN ('A7', 'A8', 'A9'))
        and A1.CDU_DisponivelOnline = 1
    group by
        A1.Artigo,
        A1.Descricao
sql sql-server subquery min
)
)
WHERE RN = 1

您可以查看以下链接以获取更多关于ROW_NUMBER()的详细信息

https://docs.microsoft.com/en-us/sql/t-sql/functions/row-number-transact-sql?view=sql-server-ver15

【讨论】:

  • 无法正常工作。我只需要一个查询来将这两个子查询的 MIN 值放在一起,但它需要在那个主查询上
猜你喜欢
  • 2016-07-09
  • 2018-10-21
  • 2022-11-25
  • 1970-01-01
  • 2021-12-24
  • 1970-01-01
  • 2018-04-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多