将随机选择的列添加到结果中

时间:2017-12-06 11:12:36

标签: sql oracle query-optimization

我想知道是否有更优化的查询来从数据库中获取我想要的内容。

我的数据库架构如下:

表1: (NUM_T1C1; ID_T1C2)

表2: (ID_T2C1; RES_T2C2)

首先,我想得到一个定义为:

的随机行
SELECT NUM_T1C1, ID_T2C1
FROM (
    SELECT T1.NUM_T1C1, T2.ID_T2C1, DBMS_RANDOM.VALUE
    FROM TABLE1 T1, TABLE2 T2
    WHERE T1.NUM_T1C1 IS NOT NULL
    AND T2.RES_T2C2 IS NOT NULL
    AND T1.ID_T1C2 = T2.ID_T2C1
    ORDER BY 3
) WHERE ROWNUM = 1

我将调用此查询:QUERY1。

我的问题如下,我希望得到一行(random NUM_T1C1 != QUERY1.NUM_T1C1; ID_T2C1 == QUERY1.ID_T2C1),所以我尝试过:

SELECT NUM_T1C1, ID_T2C1
FROM (
    SELECT R2.NUM_T1C1, R1.ID_T2C1, DBMS_RANDOM.VALUE
    FROM (
        SELECT NUM_T1C1, ID_T2C1
        FROM (
            SELECT T1.NUM_T1C1, T2.ID_T2C1, DBMS_RANDOM.VALUE
            FROM TABLE1 T1, TABLE2 T2
            WHERE T1.NUM_T1C1 IS NOT NULL
            AND T2.RES_T2C2 IS NOT NULL
            AND T1.ID_T1C2 = T2.ID_T2C1
            ORDER BY 3
        ) WHERE ROWNUM = 1
    ) R1, TABLE1 R2
    WHERE R2.NUM_T1C1 <> R1.NUM_T1C1
    ORDER BY 3
) WHERE ROWNUM = 1

它正在运行,但我认为这不是最佳方式。 有没有更好的方法来获得预期的结果?

编辑:

我找到另一种获取随机行的方法,但我仍然不知道它是否是最佳的:

SELECT NUM_T1C1, ID_T2C1
FROM (
    SELECT R1.NUM_T1C1, R2.ID_T2C1
    FROM
    (
        SELECT T1.NUM_T1C1, T2.ID_T2C1, DBMS_RANDOM.VALUE
        FROM TABLE1 T1, TABLE2 T2
        WHERE T1.NUM_T1C1 IS NOT NULL
        AND T2.T2C2 IS NULL
        AND T1.ID_T1C2 = T2.ID_T2C1
        ORDER BY 3
    ) R1,
    (
        SELECT T2.ID_T2C1, DBMS_RANDOM.VALUE
        FROM TABLE1 T1, TABLE2 T2
        WHERE T1.NUM_T1C1 IS NOT NULL
        AND T2.T2C2 IS NOT NULL
        AND T1.ID_T1C2 = T2.ID_T2C1
        ORDER BY 2
    ) R2
) WHERE ROWNUM = 1

以下是一个例子:

        Table1                  Table2
+----------+---------+  +---------+----------+
| NUM_T1C1 | ID_T1C2 |  | ID_T2C1 | RES_T2C2 |
+----------+---------+  +---------+----------+
| 23       | 5       |  | 9       | NULL     |
| 521      | 4       |  | 4       | DG_513   |
| 71       | 7       |  | 7       | FN_731   |
| 97       | 9       |  | 5       | NULL     |
+----------+---------+  +---------+----------+

结果将是其中之一(随机选择一个):

+----------+---------+
| NUM_T1C1 | ID_T2C1 |
+----------+---------+
| 23       | 4       |
| 23       | 7       |
| 97       | 4       |
| 97       | 7       |
+----------+---------+

1 个答案:

答案 0 :(得分:0)

这是一种只有一个(交叉)连接的方法:

SQL Fiddle

Oracle 11g R2架构设置

CREATE TABLE Table1 ( NUM_T1C1, ID_T1C2 ) AS
SELECT  23, 5 FROM DUAL UNION ALL
SELECT 521, 4 FROM DUAL UNION ALL
SELECT  71, 7 FROM DUAL UNION ALL
SELECT  97, 9 FROM DUAL;

CREATE TABLE Table2 ( ID_T2C1, RES_T2C2 ) As
SELECT 9, NULL     FROM DUAL UNION ALL
SELECT 4, 'DG_513' FROM DUAL UNION ALL
SELECT 7, 'FN_731' FROM DUAL UNION ALL
SELECT 5, NULL     FROM DUAL;

查询1

SELECT NUM_T1C1, ID_T2C1
FROM   (
  SELECT NUM_T1C1,
         ID_T2C1,
         COUNT( CASE WHEN T1.ID_T1C2 = T2.ID_T2C1 THEN 1 END )
           OVER ( PARTITION BY T1.NUM_T1C1 ) AS num_matches
  FROM   Table1 T1
         CROSS JOIN
         (
           SELECT *
           FROM   Table2
           WHERE  RES_T2C2 IS NOT NULL
         ) T2
  ORDER BY DBMS_RANDOM.VALUE
)
WHERE  num_matches = 0
--AND    ROWNUM = 1

<强> Results

| NUM_T1C1 | ID_T2C1 |
|----------|---------|
|       23 |       7 |
|       97 |       4 |
|       97 |       7 |
|       23 |       4 |