【问题标题】:advanced select in Stored Procedure存储过程中的高级选择
【发布时间】:2011-02-12 21:15:02
【问题描述】:

我得到了这张桌子:

CREATE TABLE Test_Table (
    old_val VARCHAR2(3),
    new_val VARCHAR2(3),
    Updflag NUMBER,
    WorkNo NUMBER  );

这是在我的表中:

INSERT INTO Test_Table  (old_val, new_val, Updflag , WorkNo) VALUES('1',' 20',0,0);
INSERT INTO Test_Table  (old_val, new_val, Updflag , WorkNo) VALUES('2',' 20',0,0);
INSERT INTO Test_Table  (old_val, new_val, Updflag , WorkNo) VALUES('2',' 30',0,0);
INSERT INTO Test_Table  (old_val, new_val, Updflag , WorkNo) VALUES('3',' 30',0,0);    
INSERT INTO Test_Table  (old_val, new_val, Updflag , WorkNo) VALUES('4',' 40',0,0);
INSERT INTO Test_Table  (old_val, new_val, Updflag , WorkNo) VALUES('4',' 40',0,0);

现在我的表看起来像这样:

Row  Old_val  New_val       Updflag  WorkNo
1    '1'        ' 20'       0        0
2    '2'        ' 20'       0        0
3    '2'        ' 30'       0        0
4    '3'        ' 30'       0        0
5    '4'        ' 40'       0        0
6    '5'        ' 40'       0        0

(如果new_val 列中的值相同,则它们是在一起的,old_val 也是如此) 所以在上面的例子中,第 1-4 行在一起,第 5-6 行

目前我的存储过程中有一个光标:

 SELECT t1.Old_val, t1.New_val, t1.updflag, t1.WorkNo
    FROM Test_Table t1
    WHERE t1.New_val =
      (
        SELECT t2.New_val
        FROM Test_Table t2
        WHERE t2.Updflag = 0
          AND t2.Worknr = 0
          AND ROWNUM = 1
      )

输出是这样的:

Row  Old_val  New_val   Updflag  WorkNo
1    1         20       0        0
2    2         20       0        0

我的问题是,我不知道如何通过一次选择获得第 1 到第 4 行。 (我有 4 个子查询的想法,但如果它的更多数据匹配在一起,这将不起作用)

你们中有人有想法吗?

【问题讨论】:

  • 你能告诉我们你想要退回什么吗?您是否希望所有“在一起”的东西都返回?如果是这样,是否会返回第 1-4 行和第 5-6 行,从而返回所有行?
  • 我的帖子的底部是我现在拥有的。是的,如果我第二次使用脚本,我希望第 1-4 行返回第 5-6 行等...(选择后有更新。)我认为来自Vincent Malgrat 的答案是完美的如果我可以锁定选定的行。

标签: sql oracle stored-procedures plsql


【解决方案1】:

您可以使用分析来定义连续行组:

SQL> SELECT old_val, new_val, updflag, workno,
  2         SUM(gap) over(ORDER BY old_val, new_val) grp
  3    FROM (SELECT t.*,
  4                  CASE
  5                     WHEN new_val = lag(new_val)
  6                                    over(ORDER BY old_val, new_val)
  7                       OR old_val = lag(old_val)
  8                                    over(ORDER BY old_val, new_val)
  9                     THEN
 10                      0
 11                     ELSE
 12                      1
 13                  END gap
 14             FROM Test_Table t);

OLD_VAL NEW_VAL    UPDFLAG     WORKNO        GRP
------- ------- ---------- ---------- ----------
1        20              0          0          1
2        20              0          0          1
2        30              0          0          1
3        30              0          0          1
4        40              0          0          2
4        40              0          0          2

当当前行与前一行不在同一组时,内部 SELECT 构建一个等于 1 的“GAP”列。

外部 SELECT 使用间隙列上的运行总计来获取组号。

编辑 2

由于分析函数,您不能将 FOR UPDATE 子句直接添加到查询中。但是,您可以直接查询基表:

SQL> WITH t_new AS (
  2  SELECT t_rowid, old_val, new_val, updflag, workno,
  3         SUM(gap) over(ORDER BY old_val, new_val) grp
  4    FROM (SELECT t.*, t.rowid t_rowid,
  5                  CASE
  6                     WHEN new_val = lag(new_val)
  7                                    over(ORDER BY old_val, new_val)
  8                       OR old_val = lag(old_val)
  9                                    over(ORDER BY old_val, new_val)
 10                     THEN
 11                      0
 12                     ELSE
 13                      1
 14                  END gap
 15             FROM test_table t)
 16  )
 17  SELECT *
 18    FROM test_table
 19   WHERE ROWID IN (SELECT t_rowid
 20                     FROM t_new
 21                    WHERE grp = (SELECT grp
 22                                   FROM t_new t2
 23                                  WHERE t2.new_val = ' 20'
 24                                    AND t2.old_val = '1'))
 25     FOR UPDATE;

OLD_VAL NEW_VAL    UPDFLAG     WORKNO
------- ------- ---------- ----------
1        20              0          0
2        20              0          0
2        30              0          0
3        30              0          0

【讨论】:

  • 哦酷不知道有一个函数来获取以前的值。好吧,这很好用,但是是否可以对其进行更改,只显示 GRP 1 的行?
  • 啊它的作品:我将WHERE t2.new_val = ' 20' AND t2.old_val = '1' 更改为where rownum = 1 它具有相同的效果。
  • 可以在这个语句中使用更新吗?因为我需要锁定这些行直到它们更新?!
  • 谢谢!我用你的脚本作为子查询,它工作得很好!再次感谢!
【解决方案2】:

如果您想要的是返回“与某物在一起”的所有行,那么您的原始样本数据似乎不会提供不应返回的行。所以,让我们添加以下内容:

INSERT INTO Test_Table  (old_val, new_val, Updflag , WorkNo) VALUES('6',' 50',0,0);

此行不应与任何内容一起,也不应返回。鉴于此,我认为我们可以使用 EXISTS 来获得您想要的:

Select *
From Test_Table T1
Where Exists    (
                Select 1
                From Test_Table T2
                Where ( T2.old_val = T1.old_val Or T2.new_val = T1.new_val )
                    And ( T2.row <> T1.row )
                )

【讨论】:

  • 我在此收到错误ORA-00904:而( T2.row &lt;&gt; T1.row ) 在我的示例中,Row 仅用于显示我的意思。
  • @Auro - 然后将“row”替换为 Test_Table 的主键。
猜你喜欢
  • 1970-01-01
  • 2015-04-01
  • 1970-01-01
  • 2022-01-06
  • 1970-01-01
  • 1970-01-01
  • 2011-05-14
  • 2015-05-02
  • 2013-11-11
相关资源
最近更新 更多