将单列行集与 Oracle 中的另一个单列行集进行比较 SQL
Compare a single-column row-set with another single-column row set in Oracle SQL
有没有Oracle SQL运算符或函数,比较2个结果集是否完全相同。目前我的想法是在两个方向上都使用 MINUS 运算符,但我正在寻找一个更好、性能更好的解决方案来实现。一个结果集是固定的(见下文),另一个取决于记录。
非常重要:不允许我更改架构和结构。所以 CREATE TABLE
和 CREATE TYPE
等等。我不允许在这里。同样重要的是,必须找到解决方案的地方使用oracle11g版本。
SQL Fiddle 的 shema 是:
CREATE TABLE DETAILS (ID INT, MAIN_ID INT, VALUE INT);
INSERT INTO DETAILS VALUES (1,1,1);
INSERT INTO DETAILS VALUES (2,1,2);
INSERT INTO DETAILS VALUES (3,1,3);
INSERT INTO DETAILS VALUES (4,1,4);
INSERT INTO DETAILS VALUES (5,2,1);
INSERT INTO DETAILS VALUES (6,2,2);
INSERT INTO DETAILS VALUES (7,3,1);
INSERT INTO DETAILS VALUES (7,3,2);
现在这是我的 SQL 查询(选择 MAIN_IDs 个,其“VALUE”与给定列表完全相同):
SELECT DISTINCT D.MAIN_ID FROM DETAILS D WHERE NOT EXISTS
(SELECT VALUE FROM DETAILS WHERE MAIN_ID=D.MAIN_ID
MINUS
SELECT * FROM TABLE(SYS.ODCINUMBERLIST(1, 2)))
AND NOT EXISTS
(SELECT * FROM TABLE(SYS.ODCINUMBERLIST(1, 2))
MINUS
SELECT VALUE FROM DETAILS WHERE MAIN_ID=D.MAIN_ID)
SQL Fiddle link: http://sqlfiddle.com/#!4/25dde/7/0
如果您使用集合(而不是 VARRAY
),那么您可以将值聚合到一个集合中并直接比较两个集合:
CREATE TYPE int_list AS TABLE OF INT;
然后:
SELECT main_id
FROM details
GROUP BY main_id
HAVING CAST( COLLECT( value ) AS int_list ) = int_list( 1, 2 );
输出:
| MAIN_ID |
| ------: |
| 2 |
| 3 |
db<>fiddle here
更新
根据您在评论中展开的fiddle,您可以使用:
SELECT B.ID
FROM BUSINESS_DATA B
INNER JOIN BUSINESS_NAME N
ON ( B.NAME_ID=N.ID )
WHERE N.NAME='B1'
AND EXISTS (
SELECT business_id
FROM ORDERS O
LEFT OUTER JOIN TABLE(
SYS.ODCIDATELIST( DATE '2021-01-03', DATE '2020-04-07', DATE '2020-05-07' )
) d
ON ( o.orderdate = d.COLUMN_VALUE )
WHERE O.BUSINESS_ID=B.ID
GROUP BY business_id
HAVING COUNT( CASE WHEN d.COLUMN_VALUE IS NULL THEN 1 END ) = 0
AND COUNT( DISTINCT o.orderdate )
= ( SELECT COUNT(DISTINCT COLUMN_VALUE) FROM TABLE( SYS.ODCIDATELIST( DATE '2021-01-03', DATE '2020-04-07', DATE '2020-05-07' ) ) )
)
(注意:不要隐式地从字符串创建日期;如果用户更改他们的 NLS_DATE_FORMAT
会话,这将导致查询失败,并且查询文本没有任何更改参数。而是将 TO_DATE
与适当的格式模型或 DATE
文字一起使用。)
db<>fiddle here
有没有Oracle SQL运算符或函数,比较2个结果集是否完全相同。目前我的想法是在两个方向上都使用 MINUS 运算符,但我正在寻找一个更好、性能更好的解决方案来实现。一个结果集是固定的(见下文),另一个取决于记录。
非常重要:不允许我更改架构和结构。所以 CREATE TABLE
和 CREATE TYPE
等等。我不允许在这里。同样重要的是,必须找到解决方案的地方使用oracle11g版本。
SQL Fiddle 的 shema 是:
CREATE TABLE DETAILS (ID INT, MAIN_ID INT, VALUE INT);
INSERT INTO DETAILS VALUES (1,1,1);
INSERT INTO DETAILS VALUES (2,1,2);
INSERT INTO DETAILS VALUES (3,1,3);
INSERT INTO DETAILS VALUES (4,1,4);
INSERT INTO DETAILS VALUES (5,2,1);
INSERT INTO DETAILS VALUES (6,2,2);
INSERT INTO DETAILS VALUES (7,3,1);
INSERT INTO DETAILS VALUES (7,3,2);
现在这是我的 SQL 查询(选择 MAIN_IDs 个,其“VALUE”与给定列表完全相同):
SELECT DISTINCT D.MAIN_ID FROM DETAILS D WHERE NOT EXISTS
(SELECT VALUE FROM DETAILS WHERE MAIN_ID=D.MAIN_ID
MINUS
SELECT * FROM TABLE(SYS.ODCINUMBERLIST(1, 2)))
AND NOT EXISTS
(SELECT * FROM TABLE(SYS.ODCINUMBERLIST(1, 2))
MINUS
SELECT VALUE FROM DETAILS WHERE MAIN_ID=D.MAIN_ID)
SQL Fiddle link: http://sqlfiddle.com/#!4/25dde/7/0
如果您使用集合(而不是 VARRAY
),那么您可以将值聚合到一个集合中并直接比较两个集合:
CREATE TYPE int_list AS TABLE OF INT;
然后:
SELECT main_id
FROM details
GROUP BY main_id
HAVING CAST( COLLECT( value ) AS int_list ) = int_list( 1, 2 );
输出:
| MAIN_ID | | ------: | | 2 | | 3 |
db<>fiddle here
更新
根据您在评论中展开的fiddle,您可以使用:
SELECT B.ID
FROM BUSINESS_DATA B
INNER JOIN BUSINESS_NAME N
ON ( B.NAME_ID=N.ID )
WHERE N.NAME='B1'
AND EXISTS (
SELECT business_id
FROM ORDERS O
LEFT OUTER JOIN TABLE(
SYS.ODCIDATELIST( DATE '2021-01-03', DATE '2020-04-07', DATE '2020-05-07' )
) d
ON ( o.orderdate = d.COLUMN_VALUE )
WHERE O.BUSINESS_ID=B.ID
GROUP BY business_id
HAVING COUNT( CASE WHEN d.COLUMN_VALUE IS NULL THEN 1 END ) = 0
AND COUNT( DISTINCT o.orderdate )
= ( SELECT COUNT(DISTINCT COLUMN_VALUE) FROM TABLE( SYS.ODCIDATELIST( DATE '2021-01-03', DATE '2020-04-07', DATE '2020-05-07' ) ) )
)
(注意:不要隐式地从字符串创建日期;如果用户更改他们的 NLS_DATE_FORMAT
会话,这将导致查询失败,并且查询文本没有任何更改参数。而是将 TO_DATE
与适当的格式模型或 DATE
文字一起使用。)
db<>fiddle here