SQL发布日期之前的最近日期的SQL连接表

时间:2016-10-18 18:15:25

标签: sql-server tsql left-join inner-join closest

(第二次编辑于2016年10月19日上午7点进一步简化代码,在代码中添加评论以根据其他人的反馈进行澄清。)

我100%卡住并寻求帮助,拜托!

这似乎是一个重复的问题,但并不是因为论坛中的其他解决方案在这种情况下不起作用。

这是对我们的ERP数据库的查询,该数据库试图获得零件的总销售成本。基本上,ERP可以轻松获得所有直接成本,但不计算废品成本。

我遇到的情况是在FROM部分的子查询中标记为:

'>>>>>> >     

现在编写的子查询将所有货物提取到我们的废料供应商并获得每磅平均每月费率,然后根据合金类型,月份和年份加入其他表格。

财务部告诉我平均值不是一个好的解决方案,一些金属价格波动太大,或者他们不会在零件运输的同一个月内卖掉废金属,所以这不会起作用。

我需要从部件从我们工厂发货之前的最近日期获得我们为废金属支付的费率。

我发现Stack Overflow上的其他示例显示了这样做的方法,但是主表和子查询表重叠,所以我见过的其他解决方案都失败了。我在下面的代码中做了评论,以显示和解释这一点。

我完全接受这个想法,我接近这个错误......如果有人能指导我如何做这项工作我真的很感激 - 我很难过去这个障碍.....

Collecting statsmodels>=0.5.0 (from mypackage)
Downloading statsmodels-0.8.0rc1.zip (9.9MB)
100% |████████████████████████████████| 9.9MB 217kB/s 
Complete output from command python setup.py egg_info:
Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/tmp/pip-build-nkf7ym2k/statsmodels/setup.py", line 330, in <module>
        from numpy.distutils.misc_util import get_info
    ImportError: No module named 'numpy'

以上是上述查询的示例输出,因为您可以看到'Scrap_Value_per_lb'失败:

DECLARE @Date_From                      AS  DATETIME;
DECLARE @Date_To                        AS  DATETIME;
SET     @Date_From                      = '2016-10-01 00:00:00.000';
SET     @Date_To                        =  GETDATE()       ;
 -- Start Main query     
SELECT TOP 10
   CCustomer.Customer_Type          AS  'Industry'
  ,SShipper.Ship_Date               AS  'Ship_Date'
  ,SSContainer.Serial_No            AS  'Serial_No'
  ,PPart.Grade                      AS  'Alloy'
  ,tbl_ScrapValue.Scrap_Value_per_lb    AS 'Scap_Value_per_lb'

FROM
            Sales_v_Shipper_Line          AS SSLine 
      JOIN  Sales_v_Shipper               AS SShipper
        ON  SShipper.Shipper_Key = SSLine.Shipper_Key
      JOIN  Part_v_Part                   AS PPart
        ON  SSLine.Part_Key = PPart.Part_Key
      JOIN  Common_v_Customer             AS CCustomer
        ON  SShipper.Customer_No   = CCustomer.Customer_No
 -- >>>>>>HELP NEEDED STARTING HERE
 -- Below is the sub query that pulls the scrap sales value per pound.
 --  The key point is that both shipments to our customers of real parts,
 --   and the 'shipments' of scrap metal sales come from the same tables,
 --  mainly Part_v_Part and Sales_v_Shipper, because of that the other 
--solutions for the 'join by closest date' in the forums don't work.

LEFT OUTER  JOIN  (SELECT
                     MONTH(SShipper.Ship_Date)       AS 'Scrap_Ship_Month'
                    ,YEAR(SShipper.SHip_Date)        AS 'Scrap_Ship_Year'
                    ,PPart.Grade                     AS  'Alloy'
                    ,AVG(AARIDist.Unit_Price)        AS 'Scrap_Value_per_lb'

                FROM
                        Sales_v_Shipper               AS  SShipper
                  JOIN  Sales_v_Shipper_Line          AS  SS_Line
                    ON  SShipper.Shipper_Key = SS_Line.Shipper_Key  
                  JOIN  Part_v_Part                   AS PPart
                    ON  SS_Line.Part_Key = PPart.Part_Key
                  JOIN  Common_v_Customer             AS  CCustomer
                    ON  SShipper.Customer_No = CCustomer.Customer_No

                WHERE CCustomer.Customer_Code     = 'Scrap_Vendor'
                AND SSHipper.Ship_Date <= @Date_To

            GROUP BY
                 MONTH(SShipper.Ship_Date)
                ,YEAR(SShipper.SHip_Date)
                ,PPart.Grade
               ) AS tbl_ScrapValue
  ON  PPart.Grade = tbl_ScrapValue.Alloy 
      AND
        YEAR(SShipper.Ship_Date) = YEAR(tbl_ScrapValue.Scrap_Ship_Year)
      AND
        MONTH(SShipper.Ship_Date) =(tbl_ScrapValue.Scrap_Ship_Month)

--- >>>>HELP NEEDED ENDS HERE
WHERE
    AND SShipper.Ship_Date >= @Date_From
    AND SSHipper.Ship_Date <= @Date_To      
 GROUP BY
      SShipper.Shipper_No
      ,SShipper.Ship_Date
      ,CCustomer.Customer_Type
      ,SSContainer.Quantity
      ,PPart.Grade

感谢您的帮助!

4 个答案:

答案 0 :(得分:0)

所以,如果我理解正确,你希望子查询只返回一行(外部查询中的每一行都相同?)

SELECT Top 1 
                     SShipper.Ship_Date
                    ,PPart.Grade                AS  'Alloy'
                    ,AARIDist.Unit_Price        AS 'Scrap_Value_per_lb'

                FROM
                        Sales_v_Shipper               AS  SShipper
                  JOIN  Sales_v_Shipper_Line          AS  SS_Line
                    ON  SShipper.Shipper_Key = SS_Line.Shipper_Key  
                  JOIN  Part_v_Part                   AS PPart
                    ON  SS_Line.Part_Key = PPart.Part_Key
                  JOIN  Common_v_Customer             AS  CCustomer
                    ON  SShipper.Customer_No = CCustomer.Customer_No
                  JOIN  Accounting_v_AR_Invoice_Dist  AS  AARIDist
                    ON  SS_Line.Shipper_Line_Key = AARIDist.Shipper_Line_Key

                WHERE CCustomer.Customer_Code     = 'Scrap_Value'
                AND SSHipper.Ship_Date <= @Date_To
                AND AARIDIst.Unit_Price < AARIDist.Quantity
                AND AARIDist.Unit_Price > '0'

                Order By SShipper.Ship_Date Desc

               ) AS tbl_SValue

如果子查询的值对于外部查询的每一行应该是不同的,那么我需要知道子查询中的每一行如何连接到外部查询中的行

答案 1 :(得分:0)

因此,当您销售某种合金的金属时,您会出售所有可用的金属,即没有剩余的金属?

然后你从购买表中取出记录,并将它们加入到同一合金的下一个销售记录中。这可以通过交叉应用来实现。这是一个包含简单表格的查询,可以让您了解所需内容:

select
  year(matched_sold.sold_date),
  month(matched_sold.sold_date),
  sum(bought.amount * bought.price)
from bought
cross apply
(
  select top 1 *
  from sold
  where sold.alloy = bought.alloy
  and sold.sold_date > bought.bought_date
  order by sold.sold_date desc
) matched_sold
group by
  year(matched_sold.sold_date),
  month(matched_sold.sold_date);

答案 2 :(得分:0)

我不知道,我的问题是否正确。您希望通过在日期字段上使用JOIN来连接两个结果集,其中没有确保完全匹配。可能你可以使用ROW_NUMBER函数来生成包括排序的分区行号,然后在行号上加入例如: ROW_NR = 1。

TABLE 1                 TABLE 2
ROW_NR DATE       ID    ROW_NR DATE       ID
------ ---------- --    ------ ---------- --
     1 10/25/2016  1 -match- 1 10/27/2016  1 
     2 10/24/2016  1        
     3 10/20/2016  1
     4 10/19/2016  1
     1 10/23/2016  2 -match- 1 10/28/2016  2
     2 10/15/2016  2        
     3 10/09/2016  2
     4 10/08/2016  2     

表1中的行编号:

  • TABLE1的数据,包含TABLE1.DATE&lt; = TABLE2.DATE

  • 按ID划分

  • 按ID和DATE DESC

  • 排序

表2中的行编号:

  • ROW_NR始终为1

通过它,您可以隐式加入数据字段而不会完全匹配。很抱歉没有提供SQL语句。

答案 3 :(得分:0)

每个人, 感谢您的反馈。我结束了,我写了这个问题可怕。我花了几个小时思考它并将示例代码进一步放下并重新发布问题: T-SQL JOIN Table On Self Based on Closest Date 我认为这更有意义,我感谢所有回复并试图帮助回答我所写内容的人。它有所帮助,但我仍然无法让它发挥作用。 再次感谢, 我