我需要能够使用TSQL在SSRS 2008中提取数据集的行。我使用了三个表product
,stock
,calls
。 product
的综合密钥为mfg
和part_number
,其他两个表中的字段为foreign keys
。 calls
表创建一行,该行对特定月份的呼叫数进行求和,并以yyyymm
格式表示月份。我想要做的是提取每个部分的最后一个电话,但我想忽略当前月份,所以我有这个:
select product.mfg, product.part_number, max(calls.yyyymm) last_call
from product inner join stock on product.mfg = stock.mfg
and product.part_number = stock.part_number
left join calls on product.mfg = calls.mfg
and product.part_number = calls.part_number
where stock.onhand > 0 and calls.yyyymm < '201202'
这项工作正常,但大约有65条记录,其中唯一的通话是'201202'
。
我尝试过nullif(max(calls.yyyymm), null)
而不是max(calls.yyyymm)
。我认为左calls
表的连接将完成它,但它似乎没有。我还在select中尝试了一些case语句的变体,即:
case when max(calls.yyyymm) is not null then max(calls.yyyymm) else null end
我最终想要做的是创建两个数据集,一个用于库存零件,一个用于库存零件中的调用,然后使用SSRS 2008中的查找功能创建报告,但我希望两个集合都生成相同的行数,因为这是一个移动目标。这不是我喜欢的方式,但是我们的零件经理要求我在每个月末尝试冻结数据,这就是为什么我决定尝试忽略当前月份的所有通话。对于当前月份的每个调用,我想使用下一个调用(如果存在),如果不存在,则插入null。
这是一个非常小的数据示例,我认为涵盖了所有变体。
use tempdb;
GO
CREATE TABLE dbo.product(mfg VARCHAR(32), part_number CHAR(5))
INSERT dbo.product SELECT 'mfg1','12345';
INSERT dbo.product SELECT 'mfg2','98765';
INSERT dbo.product SELECT 'mfg3','A1234';
INSERT dbo.product SELECT 'mfg4','5678A';
CREATE TABLE dbo.stock(mfg VARCHAR(32), part_number CHAR(5), onhand INT);
INSERT dbo.stock SELECT 'mfg1','12345',30;
INSERT dbo.stock SELECT 'mfg2','98765', 1;
INSERT dbo.stock SELECT 'mfg3','A1234', 9;
INSERT dbo.stock SELECT 'mfg4','5678A', 0;
CREATE TABLE dbo.calls(mfg VARCHAR(32), part_number CHAR(5), yyyymm CHAR(6));
INSERT dbo.calls SELECT 'mfg1','12345','201101';
INSERT dbo.calls SELECT 'mfg1','12345','201202';
INSERT dbo.calls SELECT 'mfg2','98765','201202';
当前结果集:
mfg part_number last_call
mfg1 12345 201101
mfg3 A1234 NULL
我想要的是什么:
mfg part_number last_call
mfg1 12345 201101
mfg2 98765 NULL
mfg3 A1234 NULL
答案 0 :(得分:1)
我认为它只需要:
SELECT p.mfg, p.part_number, last_call = max(c.yyyymm)
FROM dbo.product AS p
INNER JOIN dbo.stock AS s
ON p.mfg = s.mfg AND p.part_number = s.part_number
LEFT OUTER JOIN dbo.calls AS c
ON p.mfg = c.mfg AND p.part_number = c.part_number
AND c.yyyymm < '201202' -- only change
WHERE s.onhand > 0;
为什么呢?因为将外连接条件移动到where子句会将外连接转换为内连接。
答案 1 :(得分:1)
您使用的WHERE
子句要求calls.yyyymm
不是NULL:
select product.mfg, product.part_number, max(calls.yyyymm) last_call
from product inner join
stock on product.mfg = stock.mfg and product.part_number = stock.part_number left join
calls on product.mfg = calls.mfg and product.part_number = calls.part_number
where stock.onhand > 0 and calls.yyyymm < '201202'
如果将WHERE
子句中的那部分移动到JOIN
条件,它应该理顺:
select product.mfg, product.part_number, max(calls.yyyymm) last_call
from product inner join
stock on product.mfg = stock.mfg and product.part_number = stock.part_number left join
calls on product.mfg = calls.mfg and product.part_number = calls.part_number and calls.yyyymm < '201202'
where stock.onhand > 0