0

有人可以帮我吗?我正在尝试编写一个 SQL 查询并在 2-3 天内遇到问题。让我先定义问题。

我有 2 张桌子

  1. Payment_Schedule_Master
    [PAYMENT_SCHEDULE_MASTER_ID] [int] NOT NULL,主键
    [FPI_ID] [varchar](9) 非空,
    [DELETE_FLAG] [char](1) 非空,
    [CREATED_BY] [varchar](30) 非空,
    [创建日期] [日期时间] 不为空,
    [MODIFY_BY] [varchar](30) 非空,
    [MODIFY_DATE] [日期时间] 非空
  1. Payment_Schedule_Detail
    [PAYMENT_SCHEDULE_DETAIL_ID] [int] IDENTITY(1,1) NOT NULL,主键
    [PAYMENT_SCHEDULE_MASTER_ID] [int] NOT NULL,主表的外键
    [PAY_YEAR] [int] 非空,
    [PAY_MONTH] [int] 非空,
    [实际] [钱] NULL,
    [预测] [钱] NULL,
    [DELETE_FLAG] [char](1) 非空,
    [CREATED_BY] [varchar](30) 非空,
    [创建日期] [日期时间] 不为空,
    [MODIFY_BY] [varchar](30) 非空,
    [MODIFY_DATE] [日期时间] 非空

两者之间存在一对多的关系:Master有一个条目,detail有多个。Payment_Schedule_Detail有一个id,外键,实际,预测和许多列。实际和预测中将包含数值。

问题:
我想得到那些等于 0的Payment_Schedule_Master行。ActualForeCast

我的查询:

我试过这个查询

Select 
   t.PAYMENT_SCHEDULE_MASTER_ID, psm.FPI_ID, 
   t.ActualSum, t.ForecastSum
from 
    (Select 
        SUM(Actual) As ActualSum, 
        SUM (forecast) AS ForecastSum, 
        PAYMENT_SCHEDULE_MASTER_ID
     from 
        [dbo].[PAYMENT_SCHEDULE_DETAIL]
     group by 
        PAYMENT_SCHEDULE_MASTER_ID) t
Inner Join 
    dbo.PAYMENT_SCHEDULE_MASTER psm on psm.PAYMENT_SCHEDULE_MASTER_ID = t.PAYMENT_SCHEDULE_MASTER_ID
where  
    t.ActualSum = t.ForecastSum
and t.ActualSum = 0

这个查询的问题是,如果Actual一月份有 200 个,十二月份有 -200 个,它也会选择那个标题,因为SUM (Actual)它是 0,这是错误的。

我不确定如何修改查询,它应该只获取那些实际为 0 和预测为 0 的标题。

测试:
以及是否有人会让我知道如何测试该方法?

更新:尝试了这个查询,但需要 8 秒。

Select 
    t.PAYMENT_SCHEDULE_MASTER_ID, psm.FPI_ID, 
    t.ActualSum, t.ForecastSum, psd.ACTUAL, psd.FORECAST
from 
    (Select 
         SUM(Actual) As ActualSum, SUM (forecast) AS ForecastSum, 
         PAYMENT_SCHEDULE_MASTER_ID
     from 
          [dbo].[PAYMENT_SCHEDULE_DETAIL]
     group by 
          PAYMENT_SCHEDULE_MASTER_ID) t
Inner Join 
     dbo.PAYMENT_SCHEDULE_MASTER psm on psm.PAYMENT_SCHEDULE_MASTER_ID = t.PAYMENT_SCHEDULE_MASTER_ID
Inner Join 
     [dbo].[PAYMENT_SCHEDULE_DETAIL] psd on psm.PAYMENT_SCHEDULE_MASTER_ID = psd.PAYMENT_SCHEDULE_MASTER_ID
 where  
     t.ActualSum = t.ForecastSum
     and t.ActualSum = 0
     and psd.ACTUAL = 0 
order by 
     psm.FPI_ID

数据和输出:

psm_id  Actual      ForeCast  [other columns]
900     10000.00    0.00
900     -10000.00   0.00
900     0.00        0.00
912     0.00        0.00
912     0.00        0.00
912     0.00        0.00

psm_id = Payment_Schedule_Master_ID

Payment_Schedule_Master_Id900实际总和为 0,它不应该出现在结果中。但912会出现在结果中,因为所有记录都是 0。我希望这会有所帮助。

4

8 回答 8

3

关于什么 -

select * from Payment_Schedule_Master
where NOT EXISTS
 (
     SELECT  null FROM  Payment_Schedule_Detail 
        where (forecast != 0 or actual != 0) and 
        Payment_Schedule_Master.id = PAYMENT_SCHEDULE_MASTER_ID
 ) 

请注意,这也会找到没有任何相关 payment_schedule_details 行的 Payment_Schedule_Master。

于 2012-12-27T15:47:35.873 回答
0

要进行测试,您可以使用 SQL Fiddle 之类的东西。

试试这个

我尝试以下 SQL

select *
from Payment_Schedule_Master mast
where ((select sum(actual) from Payment_Schedule_Detail where main = mast.id) = 0)
and ((select sum(forecast) from Payment_Schedule_Detail where main = mast.id) = 0)

它更简单,我认为它可以满足您的需求

于 2012-12-27T10:46:10.013 回答
0
Select 
    t.PAYMENT_SCHEDULE_MASTER_ID, psm.FPI_ID, 
    t.ActualSum, t.ForecastSum, psd.ACTUAL, psd.FORECAST
from 
    (Select t1.ActualSum,t1.ForecastSum,t1.PAYMENT_SCHEDULE_MASTER_ID
    from
    (Select 
         SUM(Actual) As ActualSum, SUM (forecast) AS ForecastSum, PAYMENT_SCHEDULE_MASTER_ID
     from 
          [CILS].[dbo].[PAYMENT_SCHEDULE_DETAIL]
     group by 
          PAYMENT_SCHEDULE_MASTER_ID) t1
          where  
     t1.ActualSum = 0 and t1.ForecastSum=0)t    

Inner Join 
     [Cils].dbo.PAYMENT_SCHEDULE_MASTER psm on psm.PAYMENT_SCHEDULE_MASTER_ID = t.PAYMENT_SCHEDULE_MASTER_ID
Inner Join 
     [CILS].[dbo].[PAYMENT_SCHEDULE_DETAIL] psd on psm.PAYMENT_SCHEDULE_MASTER_ID = psd.PAYMENT_SCHEDULE_MASTER_ID
order by 
     psm.FPI_ID
于 2012-12-27T10:47:21.307 回答
0

您的原始查询非常接近您的需要。您正在寻找实际和预测始终为零的情况。好吧,如果它们总是 0,那么绝对值之和就是 0。所以试试这个:

Select 
   t.PAYMENT_SCHEDULE_MASTER_ID, psm.FPI_ID, 
   t.ActualAbsSum, t.ForecastAbsSum
from 
    (Select 
        SUM(abs(Actual)) As ActualAbsSum, 
        SUM(abs(forecast)) AS ForecastAbsSum, 
        PAYMENT_SCHEDULE_MASTER_ID
     from 
        [dbo].[PAYMENT_SCHEDULE_DETAIL]
     group by 
        PAYMENT_SCHEDULE_MASTER_ID) t
Inner Join 
    dbo.PAYMENT_SCHEDULE_MASTER psm on psm.PAYMENT_SCHEDULE_MASTER_ID = t.PAYMENT_SCHEDULE_MASTER_ID
where  
    t.ForecastAbsSum = 0 and t.ActualAbsSum = 0

您是否试图获得它们为 0 的任何示例,例如:

Select psm.*
from dbo.PAYMENT_SCHEDULE_MASTER psm 
where psm.PAYMENT_SCHEDULE_MASTER_ID in (select PAYMENT_SCHEDULE_MASTER_ID
                                         from [PAYMENT_SCHEDULE_DETAIL]
                                         where actual = 0 and forecast = 0
                                        )

为了清楚起见,这使用了in而不是 a join(两者在 SQL Server 引擎中的实现方式大致相同)。

于 2012-12-27T14:43:55.103 回答
0

在我看来,您需要在求和之前在“实际”和“预测”列上使用位置:

Select 
   t.PAYMENT_SCHEDULE_MASTER_ID, psm.FPI_ID, 
   t.ActualSum, t.ForecastSum
from 
    (Select 
        SUM(Actual) As ActualSum, 
        SUM (forecast) AS ForecastSum, 
        PAYMENT_SCHEDULE_MASTER_ID
     from 
        [dbo].[PAYMENT_SCHEDULE_DETAIL]
     where Actual=0 and forecast=0
     group by 
        PAYMENT_SCHEDULE_MASTER_ID) t
Inner Join 
    dbo.PAYMENT_SCHEDULE_MASTER psm on psm.PAYMENT_SCHEDULE_MASTER_ID = t.PAYMENT_SCHEDULE_MASTER_ID

话虽如此,如果性能是一个问题,您不需要对实际和预测求和,因为您是在求和零。然后我们可以做的更简单:

Select 
   t.PAYMENT_SCHEDULE_MASTER_ID, psm.FPI_ID, 0 as ActualSum, 0 as ForecastSum
from
    (Select distinct
        PAYMENT_SCHEDULE_MASTER_ID
     from 
        dbo.PAYMENT_SCHEDULE_DETAIL
     where Actual=0 and forecast=0 ) t
Inner Join 
    dbo.PAYMENT_SCHEDULE_MASTER psm
On psm.PAYMENT_SCHEDULE_MASTER_ID = t.PAYMENT_SCHEDULE_MASTER_ID

我在性能优化方面不太聪明 - 如果您的子查询产生很多行,那么在加入之前选择不同的行,如上所述,可能会更快。但你可以试试这个:

Select distinct
   psd.PAYMENT_SCHEDULE_MASTER_ID, psm.FPI_ID, 0 as ActualSum, 0 as ForecastSum
from
   dbo.PAYMENT_SCHEDULE_DETAIL psd
Inner Join 
   dbo.PAYMENT_SCHEDULE_MASTER psm
On
   psm.PAYMENT_SCHEDULE_MASTER_ID = psd.PAYMENT_SCHEDULE_MASTER_ID
Where
   Actual=0 and forecast=0

这更简单,但可能会更慢,因为它在过滤不同的行之前加入行。而且,不要忘记索引你的 FK,除非你正在做大量的数据写入。

于 2013-01-08T13:11:15.863 回答
0

我相信这就是您正在寻找的:

SELECT M.*
FROM Payment_Schedule_Detail D
JOIN Payment_Schedule_Master M
ON M.PAYMENT_SCHEDULE_MASTER_ID = D.PAYMENT_SCHEDULE_MASTER_ID
GROUP BY D.PAYMENT_SCHEDULE_MASTER_ID
HAVING SUM(D.Actual) = 0 AND SUM(D.Forecast) = 0

或这个:

SELECT M.*
FROM (SELECT PAYMENT_SCHEDULE_MASTER_ID,
             SUM(Actual) ActualSum, SUM(Forecast) ForecastSum
      FROM Payment_Schedule_Detail
      GROUP BY PAYMENT_SCHEDULE_MASTER_ID) D
JOIN Payment_Schedule_Master M
ON M.PAYMENT_SCHEDULE_MASTER_ID = D.PAYMENT_SCHEDULE_MASTER_ID
WHERE ActualSum = 0 AND ForecastSum = 0

不确定哪个在性能方面更好。我认为第二个会创建一个临时表,因此速度较慢,但​​它可能有点取决于优化器。

根据您使用的 SQL 数据库类型,外键可能会或可能不会自动被索引,如果没有,您应该索引您的外键。

于 2013-01-08T21:16:17.833 回答
0
SELECT psm_id, ActualSum, ForecastSum FROM
(SELECT 
    PAYMENT_SCHEDULE_MASTER_ID AS psm_id, SUM(psd.Actual) As ActualSum, SUM (psd.forecast) AS ForecastSum
FROM 
    [dbo].[PAYMENT_SCHEDULE_DETAIL] psd, dbo.PAYMENT_SCHEDULE_MASTER psm
GROUP BY PAYMENT_SCHEDULE_MASTER_ID
) ts, dbo.PAYMENT_SCHEDULE_MASTER psm1
WHERE psm1.PAYMENT_SCHEDULE_MASTER_ID = ts.psm_id
AND ts.ActualSum = 0 AND ts.ForecastSum
ORDER BY 
     psm1.FPI_ID
于 2013-01-10T18:03:02.287 回答
0

谢谢你的回答,但它根本不起作用。

在我的数据库中,有一个我没有看到的特殊情况。如果特定 Payment_Schedule_Id 的实际和预测均为 0,则它将只有一行。

Select PAYMENT_SCHEDULE_MASTER_ID from (
Select COUNT(*)  As IdCount, PAYMENT_SCHEDULE_MASTER_ID, ACTUAL , FORECAST
from PAYMENT_SCHEDULE_DETAIL
group by PAYMENT_SCHEDULE_MASTER_ID, ACTUAL, FORECAST) t
where t.IdCount = 1 
and t.ACTUAL = 0.00
and t.FORECAST = 0.00

以上是解决方案。

于 2013-01-11T16:44:36.300 回答