【问题标题】:Resolve a Left Join Query returning 20 as QTY for which 10 is the expected QTY解决返回 20 作为 QTY 的左连接查询,其中 10 是预期的 QTY
【发布时间】:2017-12-19 07:16:51
【问题描述】:

处理一个返回 MRP 和价格的不同值的查询,以及它的超过数量。在这个我有一个称为利润的标志,标记为“1”我需要总结销售报告和采购报告中的所有数量,差异应该是 10。但实际值返回为 20

我尝试的查询如下

SELECT
  CAST(dp.[MRP] AS numeric(18, 2)) AS [MRP],
  CAST(dp.[PRICE] AS numeric(18, 2)) AS [RETAIL],
  CAST(dp.[CP] AS numeric(18, 2)) AS [COST],
  SUM(CAST(dp.[QUANTITY] AS numeric(18, 2))) - ISNULL(SUM(CAST(ds.[QTY] AS numeric(18, 2))), 0) AS [QTY]
FROM [iBillDB].[dbo].[DETAILPURCHASES] dp
LEFT JOIN [iBillDB].[dbo].[DETAILSALE] ds
  ON CAST(dp.MRP AS numeric(18, 2)) = CAST(ds.MRP AS numeric(18, 2))
  AND dp.ITEMN = ds.itemn
WHERE dp.ITEMN = '1'
AND dp.PROFIT = '1'
AND ds.PROFIT = '1'
GROUP BY dp.mrp,
         dp.PRICE,
         dp.CP
HAVING SUM(CAST(dp.[QUANTITY] AS numeric(18, 2))) - ISNULL(SUM(CAST(ds.[QTY] AS numeric(18, 2))), 0) > 0

我正在处理的表格是:

详细销售:

ID SN B 项目条码 项目名称 CP 数量 UOM MRP 价格 利润净额 1 1 0 1 0001 样品 150.0 10.00 PCS 150.0 150.00 1 1500.00 2 1 0 1 0002 样品 120.0 10.00 PCS 120.0 120.00 1 1200.00 3 1 0 1 0003 样品 100.0 10.00 PCS 100.0 100.00 1 1000.00 4 1 0 1 0004 样品 100.0 -10.00 PCS 100.0 100.00 2 1000.00 6 1 0 1 0004 样品 100.0 -10.00 PCS 100.0 100.00 2 -1000.00 7 1 0 1 0005 样品 100.0 -10.00 PCS 100.0 100.00 2 -1000.00 8 1 0 1 0005 样品 100.0 -10.00 PCS 100.0 100.00 2 -1000.00 9 1 0 1 0006 样品 100.0 -10.00 PCS 100.0 100.00 1 1000.00

表2:

详细购买:

ID SN ITEMN 条形码 项目名称 CP 数量 UOM MRP 价格 利润 运费 NETAMOUNT 1 1 1 0001 样品 100.00 10.0 PCS 100.0 100.0 1 00.0 1000.00 2 1 1 0002 样品 120 10.0 PCS 120.0 120.0 1 00.0 1200.00 3 1 1 0003 样品 150 10.0 PCS 150.0 150.0 1 00.0 1500.00

利润标志用于销售和销售退货,即,如果数量为正,则为销售,负数量为销售退货。我的查询应该总结所有销售和销售退货,使其显示可用的净总数量。

提前致谢。对不起,如果我的细节令人困惑。如果需要,将提供进一步的说明。

我得到的结果查询是:

MRP 零售成本数量 100.00 100.00 100.00 20.00

【问题讨论】:

  • 明智地使用标签,您已经使用 MySQL 和 MS SQL Server 标记了您的问题。你用的是哪一个?
  • WHERE 子句中有ds.PROFIT='1',其中ds 是左连接表的别名。由于这要求存在 ds 行,因此您可以有效地将左连接减少为内连接。
  • 我正在使用 SQL Server 2008 进行此查询
  • 内连接不起作用,因为它只显示两个表中的可用数据。我在两个表中都有一些额外的行,这与其他表中的 dosnt 相似。
  • 我没有建议你使用内连接。但是您添加了一个 WHERE 条件,该条件要求左联接表的行上的值不为空。因此,您的左连接有效地变成了内连接。请记住,左连接将用空值填充所有不匹配的行。您使用 WHERE 条件排除这些行。

标签: sql sql-server


【解决方案1】:
SELECT
  CAST(dp.[MRP] AS numeric(18, 2)) AS [MRP],
  CAST(dp.[PRICE] AS numeric(18, 2)) AS [RETAIL],
  CAST(dp.[CP] AS numeric(18, 2)) AS [COST],
  SUM(CAST(dp.[QUANTITY] AS numeric(18, 2))) 
                     - ISNULL(SUM(CAST(ds.[QTY] AS numeric(18, 2))), 0) AS [QTY]
FROM [iBillDB].[dbo].[DETAILPURCHASES] dp
LEFT JOIN [iBillDB].[dbo].[DETAILSALE] ds
  ON CAST(dp.MRP AS numeric(18, 2)) = CAST(ds.MRP AS numeric(18, 2))
    AND dp.ITEMN    = ds.itemn
    AND dp.ITEMN    = '1'
    AND dp.PROFIT   = '1'
    AND ds.PROFIT   = '1'     --<-- Instead of "where" keep this in "ON" clause
    -- Also use Select expression in the group by
GROUP BY CAST(dp.[MRP] AS numeric(18, 2)),
         CAST(dp.[PRICE] AS numeric(18, 2)),
         CAST(dp.[CP] AS numeric(18, 2))
HAVING SUM(CAST(dp.[QUANTITY] AS numeric(18, 2))) 
                        - ISNULL(SUM(CAST(ds.[QTY] AS numeric(18, 2))), 0) > 0

【讨论】:

  • 仍然无法按预期返回所有销售数量为 Null/0
【解决方案2】:

只需使用OUTER APPLY 即可检索您想要的输出。实际上,您的表设计不太适合LEFT JOIN,因此它从[DETAILPURCHASES] 返回重复值应该返回3 行但返回4 行,所以请尝试以下查询,在这种情况下它将是一个很好的方法

SELECT
  CAST(dp.[MRP] AS numeric(18, 2)) AS [MRP],
  CAST(dp.[PRICE] AS numeric(18, 2)) AS [RETAIL],
  CAST(dp.[CP] AS numeric(18, 2)) AS [COST],
  SUM(CAST(dp.[QUANTITY] AS numeric(18, 2)) - ds.[QTY]) AS [QTY]
FROM [iBillDB].[dbo].[DETAILPURCHASES] dp
OUTER APPLY(SELECT ISNULL(SUM(CAST(ds.[QTY] AS numeric(18, 2))), 0) qty 
            FROM [iBillDB].[dbo].[DETAILSALE] ds
            WHERE CAST(dp.MRP AS numeric(18, 2)) = CAST(ds.MRP AS numeric(18, 2))
            AND dp.ITEMN = ds.itemn
            AND dp.PROFIT = ds.PROFIT) ds
WHERE dp.ITEMN = '1'
AND dp.PROFIT = '1'
GROUP BY dp.mrp,
         dp.PRICE,
         dp.CP
HAVING SUM(CAST(dp.[QUANTITY] AS numeric(18, 2)) - ds.[QTY]) > 0

输出:

MRP     RETAIL  COST    QTY
100.00  100.00  100.00  10.00

【讨论】:

    【解决方案3】:

    我想我得到了答案,谢谢你的帮助

    查询看起来像:

    SELECT
      CAST(dp.[MRP] AS numeric(18,2)) AS [MRP],
      CAST(dp.[PRICE] AS numeric(18,2)) AS [RETAIL],
      CAST(dp.[CP] AS numeric(18,2)) AS [COST],
      (
        SELECT SUM(cast( quantity as numeric(18,2)))
        from [iBillDB].[dbo].[DETAILPURCHASES]
        where ITEMN = dp.itemn
        and cast([MRP] as numeric(18,2)) = CAST(dp.[MRP] AS numeric(18,2))
      ) -
      (
        SELECT SUM(cast( IGST as numeric(18,2)))
        from [iBillDB].[dbo].DETAILSALE
        where ITEMN = dp.ITEMN
        and cast([MRP] as numeric(18,2)) = CAST(dp.[MRP] AS numeric(18,2))
      )
    FROM [iBillDB].[dbo].[DETAILPURCHASES] dp
    WHERE dp.ITEMN = '1'
    and
    (
      SELECT SUM(cast( quantity as numeric(18,2)))
      from [iBillDB].[dbo].[DETAILPURCHASES]
      where ITEMN = dp.itemn
      and cast([MRP] as numeric(18,2)) = CAST(dp.[MRP] AS numeric(18,2))
    ) -
    (
      SELECT SUM(cast( IGST as numeric(18,2)))
      from [iBillDB].[dbo].DETAILSALE
      where ITEMN = dp.ITEMN
      and cast([MRP] as numeric(18,2)) = CAST(dp.[MRP] AS numeric(18,2))
    ) > 0
    

    【讨论】:

    • 至少您可以检查我提供的解决方案,您是否同意。如果您支持更好、更易于理解和更具可读性的解决方案,那么它对其他人也将有很大帮助。
    【解决方案4】:

    您似乎想显示两个表中每个项目的数量。所以建立总和,然后加入:

    select 
      coalesce(p.itemn, s.itemn) as itemn,
      coalesce(p.qty, 0) as purchases,
      coalesce(s.qty, 0) as sales,
      coalesce(p.qty, 0) - coalesce(s.qty, 0) as rest
    from
    (
      select itemn, sum(quantity) as qty
      from detailpurchases
      where profit = 1
      group by itemn
    ) p
    full outer join
    (
      select itemn, sum(qty) as qty
      from detailsale
      where profit = 1
      group by itemn
    ) s on s.itemn = p.itemn;
    

    这会为每个项目提供一个结果行。如果您想要每件商品的一行 + MRP + 价格,请将其添加到 GROUP BY 子句和 ON 子句中。

    如果您只想对第 1 项进行此查询,请将 where 子句添加到子查询或末尾。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-24
      • 1970-01-01
      • 1970-01-01
      • 2015-11-01
      • 1970-01-01
      • 2017-01-20
      相关资源
      最近更新 更多