我有多个Stored Procedures
加入了类似where子句的连接,实际上唯一的区别是FROM
表。如果可能的话,我想删除重复。这是一个有效的例子:
SELECT x.Month_Name
, x.Invoice_Amt
, y.Payment_Amt
FROM
(
SELECT d.Month_Name
, d.Month
, sum(i.Amount) AS Invoice_Amt
FROM Invoice i
INNER JOIN DATE d ON i.Trans_Date = d.PK_Date
WHERE d.Month BETWEEN '2016-01-01' AND '2016-02-01'
AND i.Account = '1-AAA'
GROUP BY d.Month
, d.Month_Name
) x
JOIN
(
SELECT d.Month_Name
, sum(p.Amount) AS Payment_Amt
FROM Payment p
INNER JOIN DATE d ON p.Payment_Date = d.PK_Date
WHERE d.Month BETWEEN '2016-01-01' AND '2016-02-01'
AND p.Account = '1-AAA'
GROUP BY d.month
, d.month_Name
) y ON x.Month_Name = y.Month_Name
ORDER BY x.Month
, x.Month_Name;
这是我的目标的一个非工作的例子:
SELECT d.Month_Name
, d.Month
, sum(i.Amount) AS Invoice_Amt
, sum(p.Amount) AS Payment_Amt
FROM Invoice i
INNER JOIN DATE d ON i.Trans_Date = d.PK_Date
JOIN Payment p ON i.Account = p.Account
WHERE d.Month BETWEEN '2016-01-01' AND '2016-02-01'
AND i.Account = '1-AAA'
GROUP BY d.Month
, d.Month_Name
ORDER BY d.Month
, d.Month_Name;
我无法让SQL Fiddle工作的数据库模式。
CREATE TABLE Date
(PK_Date datetime,
Month datetime,
Month_Name varchar(20));
INSERT INTO Date
VALUES
('2016-01-01', '2016-01-01', 'January 2016'),
('2016-01-15', '2016-01-01', 'January 2016'),
('2016-02-04', '2016-02-01', 'February 2016'),
('2016-02-15', '2016-02-01', 'February 2016');
CREATE TABLE Invoice
(Account varchar(15),
Trans_Date datetime,
Amount float);
INSERT INTO Invoice
VALUES
('1-AAA', '2016-01-01', 521.32),
('1-AAA', '2016-02-04', 854.20);
CREATE TABLE Payment
(Account varchar(15),
Payment_Date datetime,
Amount float);
INSERT INTO Payment
VALUES
('1-AAA', '2016-01-15', 410.50),
('1-AAA', '2016-02-15', 120.98);
答案 0 :(得分:2)
我会使用[DATE]作为基本表并离开外部联接[Invoice]& [付款]。 像这样:
SELECT d.Month_Name
, d.Month
, sum(i.Amount) AS Invoice_Amt
, sum(p.Amount) AS Payment_Amt
FROM DATE d
LEFT OUTER JOIN Invoice i ON i.Trans_Date = d.PK_Date
LEFT OUTER JOIN Payment p ON p.Payment_Date = d.PK_Date
WHERE d.Month BETWEEN '2016-01-01' AND '2016-02-01'
AND (i.Account = '1-AAA' OR p.Account = '1-AAA')
GROUP BY d.Month
, d.Month_Name
ORDER BY d.Month
, d.Month_Name;
答案 1 :(得分:0)
您根本不需要[日期]表。 Updated query >>
DECLARE @dt_from DATETIME = '2016-01-01';
DECLARE @dt_to DATETIME = '2016-02-01';
DECLARE @acc VARCHAR(256) = '1-AAA';
SELECT
[Month_Name] = DATENAME(MONTH, [agg_data].[dt]) + SPACE(1) + CAST(DATEPART(YEAR, [agg_data].[dt]) AS VARCHAR(4))
-- ,[Month] = [agg_data].[dt]
,[Invoice_Amt] = [agg_data].[amount_inv]
,[Payment_Amt] = [agg_data].[amount_pmt]
FROM
(
SELECT
[dt] = ISNULL([i].[dt], [p].[dt])
,[amount_inv] = ISNULL([i].[amount], 0)
,[amount_pmt] = ISNULL([p].[amount], 0)
,[acc] = ISNULL([i].[acc], [p].[acc])
FROM
(
SELECT
[acc] = [account]
,[dt] = DATEFROMPARTS(YEAR([trans_date]), MONTH([trans_date]), 1)
,[amount] = SUM([amount])
FROM
[invoice]
GROUP BY
DATEFROMPARTS(YEAR([trans_date]), MONTH([trans_date]), 1)
,[account]
) AS [i]
FULL JOIN
(
SELECT
[acc] = [account]
,[dt] = DATEFROMPARTS(YEAR([payment_date]), MONTH([payment_date]), 1)
,[amount] = SUM([amount])
FROM
[payment]
GROUP BY
DATEFROMPARTS(YEAR([payment_date]), MONTH([payment_date]), 1)
,[account]
) AS [p]
ON
[i].[acc] = [p].[acc]
AND [i].[dt] = [p].[dt]
) AS [agg_data]
WHERE
[dt] BETWEEN @dt_from AND @dt_to
AND [acc] = @acc
ORDER BY
[dt] ASC;