我有一个表(在Oracle 12中,但我想只使用ANSI SQL),定义和填充如下:
CREATE TABLE MYTABLE (GROOM VARCHAR2(50), BRIDE VARCHAR2(50), STATE VARCHAR2(50));
INSERT INTO MYTABLE (GROOM,BRIDE,STATE) VALUES ('ALVIN','CARMEN','NJ');
INSERT INTO MYTABLE (GROOM,BRIDE,STATE) VALUES ('ALVIN','CARMEN','VA');
INSERT INTO MYTABLE (GROOM,BRIDE,STATE) VALUES ('ALVIN','ELEANOR','NJ');
INSERT INTO MYTABLE (GROOM,BRIDE,STATE) VALUES ('CARL','CARMEN','AL');
INSERT INTO MYTABLE (GROOM,BRIDE,STATE) VALUES ('CARL','ELEANOR','AL');
INSERT INTO MYTABLE (GROOM,BRIDE,STATE) VALUES ('DAVID','DIANA','NE');
INSERT INTO MYTABLE (GROOM,BRIDE,STATE) VALUES ('FRANK','DIANA','NV');
INSERT INTO MYTABLE (GROOM,BRIDE,STATE) VALUES ('MIKE',NULL,'RI');
INSERT INTO MYTABLE (GROOM,BRIDE,STATE) VALUES ('MIKE',NULL,'WI');
我想用这个标准得到一个结果:
- 对于每个新郎(从字母顺序最低的名字),取具有字母顺序最低的名字和字母顺序最低的州(如果新娘是相同的)的“尚未结婚”的新娘。如果没有新娘可用,则将她设置为NULL。
例如:最低的新郎是Alvin,可以嫁给Carmen(新泽西州和弗吉尼亚州)或Eleanor。结果是:
Alvin, Carmen, NJ
现在最低的是卡尔,可以和卡门(但她已经和阿尔文结婚了)或者埃莉诺结婚,所以结果是:
Carl, Eleanor, AL
所以最后我想得到这个结果集:
Alvin, Carmen, NJ
Carl, Eleanor, AL
David, Diana, NE
Frank, NULL, NV
Mike, NULL, RI
正如我所说的,我只想使用ANSI SQL(所以我使用Oracle的事实是不相关的),没有临时表,游标或表自连接。窗口函数是可以的。
谢谢
2条答案
按热度按时间balp4ylt1#
嗯,首先,如果你能解释一下这些限制的性质,那就太好了。
例如,当有人想用纯SQL实现逻辑时,禁止自连接可能是合理的,但禁止自连接有什么意义呢?还有,你是否认为来自同一个表的相关子查询是自连接?标量子查询呢?
看起来你想用分析(也称为窗口)函数做一些技巧,但这是不可能的,因为在这个特定的情况下,因为你需要跟踪到目前为止已经保留了哪些新娘,而分析函数没有任何状态。
在Oracle中,有两种典型的方法可以处理类似于您的任务(“迭代”行并维护某些“状态”)
让我从模型开始,尽管它是非常特定的Oracle特性
在此解决方案中,
reserved
列用于标记bride“已分配”的每一行。此方法仅适用于最初引入model子句的Oracle版本10g Release 1。第二个解决方案如下
在这个解决方案中,您可以摆脱特定的Oracle功能
keep dense_rank
,并避免使用仅在12c中引入的cross apply
。此外,您可以使用集合而不是连接字符串来跟踪保留的新娘,但...再次,这是Oracle特定的解决方案。然而,这个(经过微小的修改)可以被采用到,比如说SQL Server。
PS
说到性能,递归解决方案在每次执行递归成员时都会扫描整个mytable,这使得它在任何相对较大的数据集上都不可行。
model
可能在数千行上很好,但它仍然为每行计算聚合(max(reserved)
),这在非SQL方法中可以避免。z9smfwbn2#
我对下面的查询做了一些测试。我不确定,所以请不要把它当作一个建议的解决方案(如果你发现一些概念上或事实上的错误,那将是非常感激的)。
这个想法是识别新郎和新娘的有序列表(通过窗口函数),然后如果新娘的排名上级配对的新郎,则更改新娘的名字,以便随后排除她的新郎分组并使用min运算符。
p.s.使用'ZZZZZZZZ'这个名字显然不是'优雅',但在我的真实的情况中,我正在处理数字,所以它可以被认为是最大数值常量的替代品。
编辑:我在这些天做了很多测试,似乎上面的查询符合我的所有需求。