暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle 矩阵乘法查询

askTom 2014-12-03
502

问题描述

嗨,汤姆,

为了证明Oracle SQL对于解决数学问题或好奇心来说足够强大,您能否将查询共享给我们以生成矩阵乘法结果。我认为它可以用“仅模型”子句来实现。

是否可以使用分析函数Lag和Lead函数来编写?
      
  
      __   __          __      __ 
     | 6 7 -4|        | 5 -1 6 -3| 
M1=  | 0 4  1|   M2=  | 0  4 1  7|   
     | 2 -2 3|        | 8  2 9  3|  
     |_     _|        |_        _|  


 M1 x M2 =  
 __                                                                      __
| 6×5 + 7×0 + -4×8  6×-1 + 7×4 + -4×2  6×6 + 7×1 + -4×9  6×-3 + 7×7 + -4×3 |
| 0×5 + 4×0 +  1×8  0×-1 + 4×4 + 1×2   0×6 + 4×1 + 1×9   0×-3 + 4×7 + 1×3  |
| 2×5 + -2×0 + 3×8  2×-1 + -2×4 + 3×2  2×6 + -2×1 + 3×9  2×-3 + -2×7 + 3×3 |
|__                                                                      __|  

 Result = 
 __                __
|-2    14     7    19|     
|8     18    13    31|
|34    -4    37   -11|
|__                __|

CREATE TABLE m1 (c1 number, c2 number, c3 number)
/
CREATE TABLE m2 (col1 number, col2 number, col3 number,col4 number)
/
INSERT INTO m1 VALUES (6,7,-4)
/
INSERT INTO m1 VALUES (0,4,1)
/
INSERT INTO m1 VALUES (2,-2,3)
/
COMMIT;

SELECT * FROM m1
/
INSERT INTO m2 VALUES (5,-1,6,-3)
/
INSERT INTO m2 VALUES (0,4,1,7)
/
INSERT INTO m2 VALUES (8,2,9,3)
/

COMMIT;

SELECT * FROM m2
/


谢谢,
博拉利

专家解答

我不得不对你的表做一点改动- -大家都知道,插入到表中的顺序并不能预测检索的顺序。因此,我们需要在那里添加一个行号- -某种单调递增的值- -以正确的顺序检索矩阵。

ops$tkyte%ORA11GR2> CREATE TABLE m1 (rn number, c1 number, c2 number, c3 number)
  2  /

Table created.

ops$tkyte%ORA11GR2> CREATE TABLE m2 (rn number, col1 number, col2 number, col3 number,col4 number)
  2  /

Table created.

ops$tkyte%ORA11GR2> INSERT INTO m1 VALUES (1, 6,7,-4)
  2  /

1 row created.

ops$tkyte%ORA11GR2> INSERT INTO m1 VALUES (2, 0,4,1)
  2  /

1 row created.

ops$tkyte%ORA11GR2> INSERT INTO m1 VALUES (3, 2,-2,3)
  2  /

1 row created.

ops$tkyte%ORA11GR2> COMMIT;

Commit complete.

ops$tkyte%ORA11GR2> 
ops$tkyte%ORA11GR2> SELECT * FROM m1
  2  /

        RN         C1         C2         C3
---------- ---------- ---------- ----------
         1          6          7         -4
         2          0          4          1
         3          2         -2          3

ops$tkyte%ORA11GR2> INSERT INTO m2 VALUES (1, 5,-1,6,-3)
  2  /

1 row created.

ops$tkyte%ORA11GR2> INSERT INTO m2 VALUES (2, 0,4,1,7)
  2  /

1 row created.

ops$tkyte%ORA11GR2> INSERT INTO m2 VALUES (3, 8,2,9,3)
  2  /

1 row created.

ops$tkyte%ORA11GR2> 
ops$tkyte%ORA11GR2> COMMIT;

Commit complete.

ops$tkyte%ORA11GR2> 
ops$tkyte%ORA11GR2> SELECT * FROM m2
  2  /

        RN       COL1       COL2       COL3       COL4
---------- ---------- ---------- ---------- ----------
         1          5         -1          6         -3
         2          0          4          1          7
         3          8          2          9          3




现在,我们需要做的是转置矩阵M2 ,使其设置友好。我们希望将M1中的第一行与M2中的第一列和M2中的第二列连接起来,依此类推。与m1中的第2行相同。所以,如果我们把M2转到它的一边,我们就可以用笛卡尔连接来获得我们所有的积分:


ops$tkyte%ORA11GR2> with d1
  2  as
  3  ( select rn, cname, val
  4      from m2
  5   unpivot ( val for cname in (COL1, COL2, COL3, COL4) )
  6  )
  7  select * from d1;

        RN CNAM        VAL
---------- ---- ----------
         1 COL1          5
         1 COL2         -1
         1 COL3          6
         1 COL4         -3
         2 COL1          0
         2 COL2          4
         2 COL3          1
         2 COL4          7
         3 COL1          8
         3 COL2          2
         3 COL3          9
         3 COL4          3

12 rows selected.

ops$tkyte%ORA11GR2> 
ops$tkyte%ORA11GR2> with d1
  2  as
  3  ( select rn, cname, val
  4      from m2
  5   unpivot ( val for cname in (COL1, COL2, COL3, COL4) )
  6  ),
  7  d2 as
  8  (
  9  select cname, x1, x2, x3
 10    from d1
 11   pivot (max(val) for rn in ( 1 as x1, 2 as x2, 3 as x3 ))
 12  )
 13  select * from d2;

CNAM         X1         X2         X3
---- ---------- ---------- ----------
COL1          5          0          8
COL2         -1          4          2
COL3          6          1          9
COL4         -3          7          3


旋转/取消旋转组合转换了我们的结果集-所以我们有两个集合,每个集合都有三个列(现在很容易相乘)。...

ops$tkyte%ORA11GR2> with d1
  2  as
  3  ( select rn, cname, val
  4      from m2
  5   unpivot ( val for cname in (COL1, COL2, COL3, COL4) )
  6  ),
  7  d2 as
  8  (
  9  select cname, x1, x2, x3
 10    from d1
 11   pivot (max(val) for rn in ( 1 as x1, 2 as x2, 3 as x3 ))
 12  ),
 13  d3 as
 14  (
 15  select c1*x1+c2*x2+c3*x3 val, rn, cname
 16    from m1, d2
 17  )
 18  select * from d3;

       VAL         RN CNAM
---------- ---------- ----
        -2          1 COL1
         8          2 COL1
        34          3 COL1
        14          1 COL2
        18          2 COL2
        -4          3 COL2
         7          1 COL3
        13          2 COL3
        37          3 COL3
        19          1 COL4
        31          2 COL4
       -11          3 COL4

12 rows selected.


我们所要做的就是将CNAME列转换为列-再次透视:

ops$tkyte%ORA11GR2> with d1
  2  as
  3  ( select rn, cname, val
  4      from m2
  5   unpivot ( val for cname in (COL1, COL2, COL3, COL4) )
  6  ),
  7  d2 as
  8  (
  9  select cname, x1, x2, x3
 10    from d1
 11   pivot (max(val) for rn in ( 1 as x1, 2 as x2, 3 as x3 ))
 12  ),
 13  d3 as
 14  (
 15  select c1*x1+c2*x2+c3*x3 val, rn, cname
 16    from m1, d2
 17  )
 18  select column1, column2, column3, column4
 19    from d3
 20   pivot (max(val) for cname in ( 'COL1' as column1, 'COL2' as column2, 'COL3' as column3, 'COL4' as column4 ))
 21   order by rn
 22  /

   COLUMN1    COLUMN2    COLUMN3    COLUMN4
---------- ---------- ---------- ----------
        -2         14          7         19
         8         18         13         31
        34         -4         37        -11



qed :)

我很期待看到所有其他的技术,其他人提出:)
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论