根据可以具有值或为空的字段选择组内的行

Posted

技术标签:

【中文标题】根据可以具有值或为空的字段选择组内的行【英文标题】:Selecting rows within group based on field that can have a value or is null 【发布时间】:2012-04-20 06:03:12 【问题描述】:

从下表中为每个 IssID FieldID 组,我想选择包含最低 ChgGrpID 值的行,如果组中存在该字段为 NULL 的行,那么仍然选择最低的非空值.如果仅存在 NULL 行,则为组选择该行。

create table #Projects
(ProjectID int, IssID int, PtID int, PTY varchar(10), TypeID int, TypeName varchar(20), FieldID int, FieldName varchar(20),         STRINGVALUE varchar(50), NUMBERVALUE int,ChgGrpID int,ChgGrpIssID int,ChgItemID int,ChgItemGrpID int,FIELD varchar(20),            NEWVALUE varchar(20), NEWSTRING varchar(20))
insert into #Projects values 
(10879,107930,3,'Super',22,'A',10648,'ADH',NULL,666,501040,107930,852895,501040,'ADH',NULL,'666')
,(10879,107930,3,'Super',22,'A',10571,'DLV','No',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL)
,(10879,107930,3,'Super',22,'A',10541,'CMPLX','Large',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL)
,(10879,107930,3,'Super',22,'A',10542,'EWF','Orange',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL)
,(10879,107930,3,'Super',22,'A',10654,'WKFL','UAT',NULL,501034,107930,852889,501034,'WKFL','DVP','CRV')
,(10879,107930,3,'Super',22,'A',10654,'WKFL','UAT',NULL,501037,107930,852892,501037,'WKFL','CRV','UAT')
,(10879,107930,3,'Super',22,'A',10654,'WKFL','UAT',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL)
,(10879,107971,3,'Super',103,'B',10648,'ADH',NULL,999,NULL,NULL,NULL,NULL,NULL,NULL,NULL)
,(10879,107971,3,'Super',103,'B',10571,'DLV','No',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL)
,(10879,107971,3,'Super',103,'B',10541,'CMPLX','Large',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL)
,(10879,107971,3,'Super',103,'B',10542,'EWF','Orange',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL)
,(10879,107971,3,'Super',103,'B',10654,'WKFL','UAT',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL)


select * from #Projects 
order by IssID, FieldID

这是我希望看到的结果:

insert into #Projects values 
(10879,107930,3,'Super',22,'A',10648,'ADH',NULL,666,501040,107930,852895,501040,'ADH',NULL,'666')
,(10879,107930,3,'Super',22,'A',10571,'DLV','No',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL)
,(10879,107930,3,'Super',22,'A',10541,'CMPLX','Large',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL)
,(10879,107930,3,'Super',22,'A',10542,'EWF','Orange',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL)
,(10879,107930,3,'Super',22,'A',10654,'WKFL','UAT',NULL,501034,107930,852889,501034,'WKFL','DVP','CRV')
,(10879,107971,3,'Super',103,'B',10648,'ADH',NULL,999,NULL,NULL,NULL,NULL,NULL,NULL,NULL)
,(10879,107971,3,'Super',103,'B',10571,'DLV','No',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL)
,(10879,107971,3,'Super',103,'B',10541,'CMPLX','Large',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL)
,(10879,107971,3,'Super',103,'B',10542,'EWF','Orange',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL)
,(10879,107971,3,'Super',103,'B',10654,'WKFL','UAT',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL)

【问题讨论】:

我讨厌这样的问题。没有冒犯,但这些都是我为我做的功课。你能试着把它分解一下,然后再发回你真正需要的帮助吗? 这不是家庭作业,我只是寻求一些建议。本质上,我需要在字段可以具有值或 NULL 的组中选择行,当有多个行并且字段中有 NULL 时,选择具有最小 NON-NULL 值的行。如果字段中只有一行为 NULL,则选择该行。 这是答案:select * from ( select *, row_number() over (partition by IssID, CustomFieldID order by Isnull(ChgGrpID, 2147483647)) as rn from #Project ) p where rn = 1 【参考方案1】:

第一个技巧是 null 是 min 选择的最后一个值 - 它们大于 min() 的任何数字,并且小于 max() 的任何数字。这意味着您想要的行为是默认行为。

第二个技巧是不能加入空值,所以需要使用isnull()。 (如果 ID 可能为 -1,则必须选择不同的替换值。)

所以我们找到我们的最小值,以及键中的其他项目,然后将其用作子查询来选择我们想要的行:

Select p.* from #Projects p
join
(Select isnull(MIN(ChgGrpID),-1) as ChgGrpID, IssID, FieldID
from #Projects 
group by IssID, FieldID) X
on isnull(P.ChgGrpID,-1)=X.ChgGrpID and P.IssID=X.IssID and P.FieldID=X.FieldID

【讨论】:

以上是关于根据可以具有值或为空的字段选择组内的行的主要内容,如果未能解决你的问题,请参考以下文章

Oracle/SQL - 在另一个表中查找或为空或可能不存在或为空的记录

选择 mongoid 中不为空或为空的位置

我正在尝试查找哪些字段为空,以便我可以从具有空的数据库中返回数据(非标量字段)

查找字段存在或为空的文档

Django - urls 中的视图或条件选择两种 url 模式中的一种,以判断参数是不是具有值或为 NONE

如何检查数据读取器是不是为空或为空