Sql server 按id从多行中选择单行
我有一个如下所示的数据库表Sql server 按id从多行中选择单行,sql-server,Sql Server,我有一个如下所示的数据库表 id | value |flag 2 null 1 2 z 2 3 x 1 3 y 2 3 z 3 4 null 2 我需要的结果如下 id | value |flag 2 z 2 3 x 1 4 null 2 如果该值为null,
id | value |flag
2 null 1
2 z 2
3 x 1
3 y 2
3 z 3
4 null 2
我需要的结果如下
id | value |flag
2 z 2
3 x 1
4 null 2
如果该值为null,则应采用其他匹配id中的值(2-z-2)。如果一个id的所有行都不是空的,那么该值应该按优先级取值,这里的优先级为1(3-x-1)。如果一个id只有空值,则获取任何一行的空值和标志在这里并不重要。此查询将获取第一个非空值(最小标志值)的值,否则获取空行的值 您的数据:
DECLARE @table TABLE
( id INT , val CHAR(1) , flag INT );
INSERT INTO @table
( id, val, flag )
VALUES ( 2, NULL, 1 )
, ( 2, 'z', 2 )
, ( 3, 'x', 1 )
, ( 3, 'y', 2 )
, ( 3, 'z', 3 )
, ( 4, NULL, 2 ); -- NULL only value
SELECT id ,
val ,
flag
FROM ( SELECT * ,
n = ROW_NUMBER() OVER ( PARTITION BY id ORDER BY CASE
WHEN val IS NULL
THEN 0
ELSE 1
END DESC, flag )
FROM @table AS t
) AS o
WHERE n = 1;
id val flag
2 z 2
3 x 1
4 NULL 1
查询:
DECLARE @table TABLE
( id INT , val CHAR(1) , flag INT );
INSERT INTO @table
( id, val, flag )
VALUES ( 2, NULL, 1 )
, ( 2, 'z', 2 )
, ( 3, 'x', 1 )
, ( 3, 'y', 2 )
, ( 3, 'z', 3 )
, ( 4, NULL, 2 ); -- NULL only value
SELECT id ,
val ,
flag
FROM ( SELECT * ,
n = ROW_NUMBER() OVER ( PARTITION BY id ORDER BY CASE
WHEN val IS NULL
THEN 0
ELSE 1
END DESC, flag )
FROM @table AS t
) AS o
WHERE n = 1;
id val flag
2 z 2
3 x 1
4 NULL 1
ROW\u NUMBER()
按id
划分,对于每个id
,它按0或1(null/非null)和标志进行排序。
case
用于先按not null
值(=1)排序,然后按null
值(=0)排序
输出:
DECLARE @table TABLE
( id INT , val CHAR(1) , flag INT );
INSERT INTO @table
( id, val, flag )
VALUES ( 2, NULL, 1 )
, ( 2, 'z', 2 )
, ( 3, 'x', 1 )
, ( 3, 'y', 2 )
, ( 3, 'z', 3 )
, ( 4, NULL, 2 ); -- NULL only value
SELECT id ,
val ,
flag
FROM ( SELECT * ,
n = ROW_NUMBER() OVER ( PARTITION BY id ORDER BY CASE
WHEN val IS NULL
THEN 0
ELSE 1
END DESC, flag )
FROM @table AS t
) AS o
WHERE n = 1;
id val flag
2 z 2
3 x 1
4 NULL 1
此查询将采用第一个not null值(最小标志值)的值,否则采用null行的值
您的数据:
DECLARE @table TABLE
( id INT , val CHAR(1) , flag INT );
INSERT INTO @table
( id, val, flag )
VALUES ( 2, NULL, 1 )
, ( 2, 'z', 2 )
, ( 3, 'x', 1 )
, ( 3, 'y', 2 )
, ( 3, 'z', 3 )
, ( 4, NULL, 2 ); -- NULL only value
SELECT id ,
val ,
flag
FROM ( SELECT * ,
n = ROW_NUMBER() OVER ( PARTITION BY id ORDER BY CASE
WHEN val IS NULL
THEN 0
ELSE 1
END DESC, flag )
FROM @table AS t
) AS o
WHERE n = 1;
id val flag
2 z 2
3 x 1
4 NULL 1
查询:
DECLARE @table TABLE
( id INT , val CHAR(1) , flag INT );
INSERT INTO @table
( id, val, flag )
VALUES ( 2, NULL, 1 )
, ( 2, 'z', 2 )
, ( 3, 'x', 1 )
, ( 3, 'y', 2 )
, ( 3, 'z', 3 )
, ( 4, NULL, 2 ); -- NULL only value
SELECT id ,
val ,
flag
FROM ( SELECT * ,
n = ROW_NUMBER() OVER ( PARTITION BY id ORDER BY CASE
WHEN val IS NULL
THEN 0
ELSE 1
END DESC, flag )
FROM @table AS t
) AS o
WHERE n = 1;
id val flag
2 z 2
3 x 1
4 NULL 1
ROW\u NUMBER()
按id
划分,对于每个id
,它按0或1(null/非null)和标志进行排序。
case
用于先按not null
值(=1)排序,然后按null
值(=0)排序
输出:
DECLARE @table TABLE
( id INT , val CHAR(1) , flag INT );
INSERT INTO @table
( id, val, flag )
VALUES ( 2, NULL, 1 )
, ( 2, 'z', 2 )
, ( 3, 'x', 1 )
, ( 3, 'y', 2 )
, ( 3, 'z', 3 )
, ( 4, NULL, 2 ); -- NULL only value
SELECT id ,
val ,
flag
FROM ( SELECT * ,
n = ROW_NUMBER() OVER ( PARTITION BY id ORDER BY CASE
WHEN val IS NULL
THEN 0
ELSE 1
END DESC, flag )
FROM @table AS t
) AS o
WHERE n = 1;
id val flag
2 z 2
3 x 1
4 NULL 1
那么你说的优先级是指标志栏?如果有多个ID与空值匹配,该怎么办?你尝试过什么,什么不起作用,等等。是的,优先权在这里。我需要1行1个id。如果多个id只有空值,那么它们将转到具有空值的单独行。我已经更新了这个问题,所以你说的优先级是指国旗栏?如果有多个ID与空值匹配,该怎么办?你尝试过什么,什么不起作用,等等。是的,优先权在这里。我需要1行1个id。如果多个id只有空值,那么它们将转到具有空值的单独行。我已经更新了这个问题。希望您不介意,我删除了您使用的突出显示引号语法(该语法应仅用于引用文本),并将其替换为粗体标题,并在我进行此操作时进行了一些SQL格式设置。@Tanner。我不介意。但我很难阅读几乎所有东西都是大写的代码。。。我个人的感觉是,在阅读时,我必须经常移动我的眼睛。但这只是我的观点。哦,没问题,我有一个SQL工具,可以为我进行格式化,就这样。如果需要,可以随时回滚和编辑自己。最主要的是引文的突出显示。这样很好。谢谢。希望你不介意,我删除了你使用的引号语法突出显示(应该只用于引用的文本),并用粗体标题替换它,并且在我使用时做了一些SQL格式设置。@Tanner。我不介意。但我很难阅读几乎所有东西都是大写的代码。。。我个人的感觉是,在阅读时,我必须经常移动我的眼睛。但这只是我的观点。哦,没问题,我有一个SQL工具,可以为我进行格式化,就这样。如果需要,可以随时回滚和编辑自己。最主要的是引文的突出显示。这样很好。谢谢