2012-08-22 47 views
1

Arrrgh,我沒有得到這個。SQL正確加入?

我有一個動態GP有7列的帳戶表。我需要填寫空白的月份,以查看某月份沒有任何活動的帳戶。

我已經有像這樣線的存儲器表@MONTHS創建的:

帳戶,說明,年,月,月份名稱,Netchange,PeriodBal


1110000,NULL,2006年, 1,NULL,0,NULL

這應該與來自Dynamics GP的相同信息相匹配。從GP類似的線應該是這樣的:

1110000,零用現金,2006年1月,15.00,343.97

如果我們沒有花任何小額現金二月,那麼將是沒有行在2/2006該帳戶,我想使@MONTHS右表與表DynamicsGP加入讓空月被填入

這裏的簡稱SQL縮短了可讀性。

SELECT Z.GPACCOUNTNO, 
Z.DESCRIPTION, 
Z.FISCALYEAR, 
Z.FISCALPERIOD, 
Z.FISCALPERIODNAME, 
Z.NETCHANGE, 
Z.PERIODBALANCE 
FROM Z 
RIGHT JOIN @MONTHS M 
    ON Z.GPACCOUNTNO = M.GPACCOUNTNO 
    AND Z.FISCALPERIOD = M.FISCALPERIOD 
    AND Z.FISCALYEAR = M.FISCALYEAR 

的SQL只是永遠運行。 (即在我失去耐心之前5分鐘)

我已驗證我的@MONTHS表看起來像我打算。我曾嘗試用兩張表做一個「聯合所有」,它給了我重複。

如果表Z不具有給定賬戶/年/月電流線,我希望我的@MONTHS表中添加該行以0

謝謝您的幫助下Netchange平衡。下面是完整的SQL。


/* Create in memory table to hold account numbers */ 
DECLARE @i int 
DECLARE @c int 
DECLARE @ACCT char(129) 
DECLARE @numrows int 
DECLARE @numyears int 
DECLARE @y int 
DECLARE @m int 
DECLARE @ACCT_TABLE TABLE (
idx smallint Primary Key IDENTITY(1,1), 
account char(129) 
) 

/* Populate account number table */ 
INSERT @ACCT_TABLE 
select distinct ACTNUMST from SBM01.[dbo].[GL00105] 

/* Year table reads available years in the DB */ 
DECLARE @YEAR_TABLE TABLE (
idx smallint Primary Key IDENTITY(1,1), 
YEAR1 smallint 
) 

/* Populate year table */ 
INSERT @YEAR_TABLE 
SELECT distinct YEAR1 FROM SBM01.dbo.SY40101 ORDER BY YEAR1 

/* Create our table of months to UNION to the main accounts */ 
DECLARE @MONTHS table (
GPACCOUNTNO char(129), 
DESCRIPTION char(51), 
FISCALYEAR smallint , 
FISCALPERIOD smallint, 
FISCALPERIODNAME char(21), 
NETCHANGE numeric(19, 5), 
PERIODBALANCE numeric(19, 5) 
) 

/* Here comes the heavy lifting. 
We loop over the account numbers and add year and month values. 
*/ 
SET @i = 1 
SET @numrows = (SELECT COUNT(*) FROM @ACCT_TABLE) 
IF @numrows > 0 
WHILE(@i <= (SELECT MAX(idx) FROM @ACCT_TABLE)) 
BEGIN 

/* Get the next account number */ 
SET @ACCT = (SELECT account FROM @ACCT_TABLE WHERE idx = @i) 
SET @c = 1 
SET @numyears = (SELECT COUNT(*) FROM @YEAR_TABLE) 
    WHILE(@c <= (SELECT MAX(idx) FROM @YEAR_TABLE)) 
    BEGIN 
     SET @y = (SELECT YEAR1 FROM @YEAR_TABLE WHERE idx = @c) 
     SET @m = '0' 
      WHILE(@m < '13') 
      BEGIN 
       INSERT INTO @MONTHS (GPACCOUNTNO, DESCRIPTION, FISCALPERIOD, FISCALYEAR, FISCALPERIODNAME, NETCHANGE, PERIODBALANCE) 
       VALUES (@ACCT, NULL, @m, @y, NULL, '0', NULL) 
       SET @m = @m + 1 
      END 
      SET @c = @c + 1 
     END 
     SET @i = @i + 1 
    END 
/* We should now have a populated Database */ 

SELECT Z.GPACCOUNTNO, Z.DESCRIPTION, Z.FISCALYEAR, Z.FISCALPERIOD, Z.FISCALPERIODNAME, Z.NETCHANGE, Z.PERIODBALANCE 
FROM (SELECT RTRIM(B.[ACTNUMST]) AS GPACCOUNTNO, 
       RTRIM(C.[ACTDESCR]) AS DESCRIPTION, 
       A.[YEAR1] AS FISCALYEAR, 
       A.[PERIODID] AS FISCALPERIOD, 
       E.[PERNAME] AS FISCALPERIODNAME, 
       ISNULL(A.[PERDBLNC], 0) AS NETCHANGE, 
       (SELECT ISNULL(SUM(D.[PERDBLNC]), 0) 
        FROM  SBM01.[dbo].[GL10110] D 
        WHERE  D.[ACTINDX] = A.[ACTINDX] 
          AND D.[YEAR1] = A.[YEAR1] 
          AND D.[PERIODID] <= A.[PERIODID] 
       ) AS PERIODBALANCE 
     FROM  SBM01.[dbo].[GL10110] A 
       INNER JOIN SBM01.[dbo].[GL00105] B ON B.[ACTINDX] = A.[ACTINDX] 
       INNER JOIN SBM01.[dbo].[GL00100] C ON C.[ACTINDX] = A.[ACTINDX] 
       INNER JOIN SBM01.[dbo].[SY40100] E ON E.[YEAR1] = A.[YEAR1] 
               AND E.[PERIODID] = A.[PERIODID] 
               AND E.[SERIES] = 0 
     UNION ALL 
     SELECT RTRIM(B.[ACTNUMST]) AS GPACCOUNTNO, 
       RTRIM(C.[ACTDESCR]) AS DESCRIPTION, 
       A.[YEAR1] AS FISCALYEAR, 
       A.[PERIODID] AS FISCALPERIOD, 
       E.[PERNAME] AS FISCALPERIODNAME, 
       ISNULL(A.[PERDBLNC], 0) AS NETCHANGE, 
       (SELECT ISNULL(SUM(D.[PERDBLNC]), 0) 
        FROM  SBM01.[dbo].[GL10111] D 
        WHERE  D.[ACTINDX] = A.[ACTINDX] 
          AND D.[YEAR1] = A.[YEAR1] 
          AND D.[PERIODID] <= A.[PERIODID] 
       ) AS PERIODBALANCE 
     FROM  SBM01.[dbo].[GL10111] A 
       INNER JOIN SBM01.[dbo].[GL00105] B ON B.[ACTINDX] = A.[ACTINDX] 
       INNER JOIN SBM01.[dbo].[GL00100] C ON C.[ACTINDX] = A.[ACTINDX] 
       INNER JOIN SBM01.[dbo].[SY40100] E ON E.[YEAR1] = A.[YEAR1] 
               AND E.[PERIODID] = A.[PERIODID] 
               AND E.[SERIES] = 0 
) Z 
RIGHT JOIN @MONTHS M 
    ON Z.GPACCOUNTNO = M.GPACCOUNTNO 
    AND Z.FISCALPERIOD = M.FISCALPERIOD 
    AND Z.FISCALYEAR = M.FISCALYEAR 
ORDER BY Z.[GPACCOUNTNO], 
    M.[FISCALYEAR], 
    M.[FISCALPERIOD] 
+0

您可以嘗試添加主鍵@months(GPACCOUNTNO,FISCALYEAR,FISCALPERIOD) –

回答

1

你爲什麼不使用@Months表作爲出發點(因爲它已經給了你一切你需要的月份),如果有可用的話,填入Z的值?

SELECT 
M.GPACCOUNTNO, 
M.DESCRIPTION, 
M.FISCALYEAR, 
M.FISCALPERIOD, 
M.FISCALPERIODNAME, 
ISNULL(Z.NETCHANGE, 0) as NETCHANGE 
ISNULL(Z.PERIODBALANCE, 0) as PERIODBALANCE 
FROM @MONTHS M 
LEFT JOIN Z 
    ON Z.GPACCOUNTNO = M.GPACCOUNTNO 
    AND Z.FISCALPERIOD = M.FISCALPERIOD 
    AND Z.FISCALYEAR = M.FISCALYEAR 
+0

如果你看一下完整的代碼,表Z是加入了巨大的混亂,等等......如何語法工作? 'SELECT M.GPACCOUNTNO, M.DESCRIPTION, M.FISCALYEAR, M.FISCALPERIOD, M.FISCALPERIODNAME, ISNULL(Z.NETCHANGE,0)作爲NETCHANGE ISNULL(Z.PERIODBALANCE,0)作爲PERIODBALANCE FROM @MONTHS中號 LEFT JOIN(SELECT BLAH FROM BLAH)z ON Z.GPACCOUNTNO = M.GPACCOUNTNO AND Z.FISCALPERIOD = M.FISCALPERIOD AND Z.FISCALYEAR = M.FISCALYEAR ORDER BY Z. [GPACCOUNTNO ], M.[FISCALYEAR], M. [FISCALPERIOD]' –

+0

首先逐個創建Z作爲臨時表,而不是在一個長SQL語句中創建它。更容易閱讀,更容易操作。您還可以分離Z表問題並優化該查詢。現在你無法確定你的性能瓶頸在哪裏。 –

+0

如果你看完整的代碼,表Z是一個巨大的混亂等等...語法是如何工作的? 'SELECT -STUFF- FROM @MONTHS m左側JOIN(SELECT BLAH FROM BLAH)z ON Z.GPACCOUNTNO = M.GPACCOUNTNO AND Z.FISCALPERIOD = M.FISCALPERIOD AND Z.FISCALYEAR = M.FISCALYEAR' 不適合我。 –

1

您可以使用SQL case語句時加入空

CREATE TABLE #TMP 
(
    id int, 
    [month] datetime 
) 
INSERT INTO #TMP(id,[month])values(1,GETDATE()) 
INSERT INTO #TMP(id,[month])values(2,null) 
INSERT INTO #TMP(id,[month])values(3,GETDATE()) 
INSERT INTO #TMP(id,[month])values(4,GETDATE()) 

CREATE TABLE #TMP2 
(
    id int, 
    [month] datetime 
) 
INSERT INTO #TMP2(id,[month])values(1,GETDATE()) 
INSERT INTO #TMP2(id,[month])values(2,GETDATE()) 
INSERT INTO #TMP2(id,[month])values(3,GETDATE()) 
INSERT INTO #TMP2(id,[month])values(4,GETDATE()) 

select * from #TMP 
select * from #TMP2 


SELECT #TMP.[id], case when #TMP.[month] is null then #TMP2.[month] else #TMP.month end 
from #tmp 
inner join #tmp2 on #tmp.id= #tmp2.id 

drop table #tmp,#tmp2