表示不存在的行或空行

发布于 2025-01-08 10:55:17 字数 2316 浏览 0 评论 0原文

我需要能够使用 TSQL 提取 SSRS 2008 中数据集的行。我使用三个表productstockcallsproduct 具有由 mfgpart_number 组成的复合键,这些字段是其他两个表中的外键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 表的左连接可以完成它,但似乎并非如此。我还尝试了选择中 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

I need to be able to extract rows for a dataset in SSRS 2008 using TSQL. I am using three tables product, stock, calls. product has a composite key of mfg and part_number and those fields are foreign keys in the other two tables. The calls table creates a row that sums the number of calls for a specific month and represents the month in the format yyyymm. What I want to do is to extract the last call for each part but I want to ignore the current month, so I have this:

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'

This works ok but there are around 65 records where the only call is in '201202'.

I have tried nullif(max(calls.yyyymm), null) instead of max(calls.yyyymm). I would think that a left join to the calls table would get it done, but it doesn't seem to. I have also tried a couple of variations of a case statement in the select, namely:

case when max(calls.yyyymm) is not null then max(calls.yyyymm) else null end

What I ultimately want to do is create two data sets, one for in stock parts and one for calls on in stock parts, then use the lookup function in SSRS 2008 to create the report, but I want both sets to generate the same number of rows since this is a moving target. This is not my preferred way of doing this but our parts manager wants me to try to freeze the data at the end of each month, which is why I decided to try ignoring all calls for the current month. For each call in the current month I want to use the next call if it exists and insert null if it doesn't.

Here is a very small example of data, I think all of the variations are covered.

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';

Current result set:

mfg       part_number          last_call
mfg1      12345                 201101
mfg3      A1234                 NULL

What I want:

mfg        part_number         last_call
mfg1       12345               201101
mfg2       98765               NULL
mfg3       A1234               NULL

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

桃扇骨 2025-01-15 10:55:17

认为只需要:

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 子句会将外连接转换为内连接。

I think it just needs to be:

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;

Why? Because moving an outer join criteria to the where clause converts the outer join to an inner join.

丢了幸福的猪 2025-01-15 10:55:17

您使用的 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

The WHERE clause you've used requires that calls.yyyymm not be 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'

If you move that part of the WHERE clause to the JOIN condition it should straighten things out:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文