2012-12-27 25 views
0

有人能幫我嗎?我正在嘗試編寫一個SQL查詢並在2-3天內遇到問題。讓我先定義問題。一對多sql查詢性能不錯

我有2個表

  1. Payment_Schedule_Master
 [PAYMENT_SCHEDULE_MASTER_ID] [int] NOT NULL, Primary key 
    [FPI_ID] [varchar](9) NOT NULL, 
    [DELETE_FLAG] [char](1) NOT NULL, 
    [CREATED_BY] [varchar](30) NOT NULL, 
    [CREATED_DATE] [datetime] NOT NULL, 
    [MODIFY_BY] [varchar](30) NOT NULL, 
    [MODIFY_DATE] [datetime] NOT NULL
  1. Payment_Schedule_Detail
 [PAYMENT_SCHEDULE_DETAIL_ID] [int] IDENTITY(1,1) NOT NULL, Primary key 
    [PAYMENT_SCHEDULE_MASTER_ID] [int] NOT NULL, Foreign key to master table 
    [PAY_YEAR] [int] NOT NULL, 
    [PAY_MONTH] [int] NOT NULL, 
    [ACTUAL] [money] NULL, 
    [FORECAST] [money] NULL, 
    [DELETE_FLAG] [char](1) NOT NULL, 
    [CREATED_BY] [varchar](30) NOT NULL, 
    [CREATED_DATE] [datetime] NOT NULL, 
    [MODIFY_BY] [varchar](30) NOT NULL, 
    [MODIFY_DATE] [datetime] NOT NULL

有一個一對多relati兩者之間的關係:Master有一個條目並且detail有很多。 Payment_Schedule_Detail有一個id,外鍵,實際,預測和很多列。實際和預測將包含數值。

問題:
我想那些Payment_Schedule_Master行具有ActualForeCast等於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] 
    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_Id 900的實際總和爲0,它不應該出現的結果。但912將出現在結果中,因爲所有記錄都是0.我希望這有助於。

+0

你能定義「好」的表現嗎?什麼是你的查詢的解釋計劃和你的表格的結構? – Ben

+0

好的表現是在1秒內。 –

+0

我用模式更新了這個問題。 –

回答

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 

上面是解決方案。

0

要測試你可以使用類似SQL小提琴的東西。

嘗試this

我嘗試以下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) 

它更簡單,我認爲它使你想要什麼

+0

你的查詢使用sum函數,如果在jan中的數量是200,在dec中是-200,那麼它將爲0,並且會帶來錯誤的標題。我用模式更新了這個問題。 –

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 
+0

我試過你的查詢,它給出了相同的結果。有很多記錄其中實際有一些值,而不是0 –

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而不是join(兩者在SQL Server引擎中大致相同)。

+0

謝謝戈登,但你的查詢仍然不能補救實際和預測的總和值的解決方案,讓我更新與示例輸出的問題。 –

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_Master不具有任何相關payment_schedule_details線。

+0

花了我五分鐘的時間來試着理解這裏所需的東西,但我相信這是正確的答案,而且這很簡單。他希望所有的細節都有0個實際和0個預測的所有主記錄。爲了避免沒有詳細信息的記錄,他可以簡單地將連接添加到存在外的詳細信息表中。這會限制結果,並且假設索引設置正確,應該不會影響性能。 –

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,除非你正在做大量的數據寫入。

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數據庫的類型,外鍵可能會自動獲取索引,也可能不會自動獲取索引,如果沒有,您應該索引您的外鍵。

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