Sql Sub Sub选择并分组:从包含组的最大值的行中获取名称列

Sql Sub Sub选择并分组:从包含组的最大值的行中获取名称列,sql,sql-server,group-by,subquery,Sql,Sql Server,Group By,Subquery,我有两张表:States和Items 说明: +----+------+-------+----------+ | id | name | state | priority | +----+------+-------+----------+ | 1 | AA | 10 | 1 | | 2 | AB | 10 | 2 | | 3 | AC | 10 | 3 | | 4 | BA | 20 |

我有两张表:States和Items

说明

+----+------+-------+----------+
| id | name | state | priority |
+----+------+-------+----------+
|  1 |   AA |    10 |        1 |
|  2 |   AB |    10 |        2 |
|  3 |   AC |    10 |        3 |
|  4 |   BA |    20 |        1 |
|  5 |   BB |    20 |        5 |
|  6 |   BC |    20 |       10 |
|  7 |   BD |    20 |       50 |
+----+------+-------+----------+
项目

+----+--------+-------+
| id | item   | state |
+----+--------+-------+
|  1 |   Blue |    10 |
|  2 |    Red |    20 |
|  3 |  Green |    20 |
|  4 | Yellow |    10 |
|  5 |  Brown |    10 |
+----+--------+-------+
priority
列未在
Items
表中使用,但会使获取所需数据变得复杂,如下所示

我想要的是
Items
表中的行列表,将每行中的
state.id
值替换为优先级最高的
name

结果如下所示:

+----+--------+-------+
| id | item   | state |
+----+--------+-------+
|  1 |   Blue |    AC |
|  2 |    Red |    BD |
|  3 |  Green |    BD |
|  4 | Yellow |    AC |
|  5 |  Brown |    AC |
+----+--------+-------+
 CREATE TABLE dbo.States(id INT, name NVARCHAR(25), state INT, priority INT);
 INSERT INTO dbo.States
 VALUES
(  1 ,'AA',    10 ,        1 ),
(  2 ,'AB',    10 ,        2 ),
(  3 ,'AC',    10 ,        3 ),
(  4 ,'BA',    20 ,        1 ),
(  5 ,'BB',    20 ,        5 ),
(  6 ,'BC',    20 ,       10 ),
(  7 ,'BD',    20 ,       50 );

CREATE TABLE dbo.Items( id INT ,item NVARCHAR(25), state INT );
INSERT INTO dbo.Items
VALUES
(  1 ,'Blue',    10 ),
(  2 ,'Red',    20 ),
(  3 ,'Green',    20 ),
(  4 ,'Yellow',    10 ),
(  5 ,'Brown',    10 );


SELECT  i.id,
        i.item,
        s.name,
        s.priority
FROM dbo.Items i
CROSS APPLY (
SELECT *,ROW_NUMBER()OVER(ORDER BY priority DESC) rn FROM dbo.States si WHERE si.state = i.state 
)s
WHERE s.rn = 1;
这是我想出的小怪物。这是最好的方法,还是我可以更高效/更少冗长?(子选项使我的手掌发痒。:-P)


更新:我使用的是MS-SQL 2005和MS-SQL 2008R2

您没有发布您的SQL Server版本。假设您使用的是2005或更高版本,则可以将ROW_NUMBER()函数与交叉应用一起使用,如下所示:

+----+--------+-------+
| id | item   | state |
+----+--------+-------+
|  1 |   Blue |    AC |
|  2 |    Red |    BD |
|  3 |  Green |    BD |
|  4 | Yellow |    AC |
|  5 |  Brown |    AC |
+----+--------+-------+
 CREATE TABLE dbo.States(id INT, name NVARCHAR(25), state INT, priority INT);
 INSERT INTO dbo.States
 VALUES
(  1 ,'AA',    10 ,        1 ),
(  2 ,'AB',    10 ,        2 ),
(  3 ,'AC',    10 ,        3 ),
(  4 ,'BA',    20 ,        1 ),
(  5 ,'BB',    20 ,        5 ),
(  6 ,'BC',    20 ,       10 ),
(  7 ,'BD',    20 ,       50 );

CREATE TABLE dbo.Items( id INT ,item NVARCHAR(25), state INT );
INSERT INTO dbo.Items
VALUES
(  1 ,'Blue',    10 ),
(  2 ,'Red',    20 ),
(  3 ,'Green',    20 ),
(  4 ,'Yellow',    10 ),
(  5 ,'Brown',    10 );


SELECT  i.id,
        i.item,
        s.name,
        s.priority
FROM dbo.Items i
CROSS APPLY (
SELECT *,ROW_NUMBER()OVER(ORDER BY priority DESC) rn FROM dbo.States si WHERE si.state = i.state 
)s
WHERE s.rn = 1;
交叉应用的工作方式类似于连接,但允许引用右侧左侧的列,如where子句所示。函数的作用是:将states表中与当前状态值匹配的所有行按相反的优先级顺序编号,以便优先级最高的行始终获得数字1。最后一个where子句只过滤掉这些行

编辑:

我刚刚开始了一个关于加入的博客系列:

交叉应用将成为第8天(2012年8月12日)的主题。

项。在您的示例数据中,state
不是
stetes.id
的外键。@Laurence:很好。更新。谢谢杰出的这正是我要找的。这是我第一次看到克罗斯申请。非常感谢。