2013-03-19 16 views
8

Próbuję napisać mnożenia macierzy dla MySQL i jestem trochę zakleszczony:MySQL mnożenia macierzy

zasadzie moi matryce są przechowywane w formacie
[wiersz #, kolumna #, matrixID, wartość], a więc na przykład matrycy [3 x 2] wyglądałby:

[row#, column#, matrixID, value] 
    1  1  mat01 1 
    1  2  mat01 2 
    1  3  mat01 3 
    2  1  mat01 4 
    2  2  mat01 5 
    2  3  mat01 6 

równoważne [[1 2 3], [4 5 6]]

następujących nie obliczanie pojedynczego elementu macierzy1 * macierzy2 dobrze :

SELECT SUM(row1.`val` * col2.`val`) 
    FROM matValues row1 
    INNER JOIN `matValues` col2 
    WHERE row1.`row` = 1 AND row1.`mID`='matrix1' AND 
     col2.`mID`='matrix2' AND col2.`col` = 1 AND row1.col = col2.row 

Zawijanie tego do funkcji, a następnie za pomocą innej funkcji do iteracji numerów wierszy i kolumn może działać, ale mam problemy z generowaniem tego zestawu liczb i iteracji nad nimi za pomocą SQL. Wszelkie porady/sugestie są mile widziane

+0

Czy naprawdę masz pytanie "Jak wygenerować sekwencję liczb w MySQL"? – raina77ow

+1

MySQL to system zarządzania bazą danych, a nie silnik algebry liniowej. Powinieneś czytać zawartość do bardziej odpowiedniego narzędzia (takiego jak aplikacja Java lub C++) wykonującego tam manipulację matrycą i, jeśli to konieczne, umieszczać wyniki z powrotem w bazie danych. – andand

+2

ofc, najprostszym rozwiązaniem jest używanie Javy lub C++ (lub cokolwiek innego), jednak mam do czynienia z bardzo dużymi macierzami (w zasadzie wystarczająco dużymi, że dopasowanie ich do pamięci nie wchodzi w rachubę) i sprawia, że ​​manipulacja matrycą w rozsądnej prędkości jest dość skomplikowana, ponieważ wymaga przechowywania tylko porcji w pamięci i obciążenia we/wy dla bardzo dużej liczby odczytów i zapisów wymaganych do przetwarzania macierzy. Jeśli chodzi o generowanie sekwencji numerów MySQL, jest to z pewnością jedno rozwiązanie i nie jestem świadomy, jak to zrobić, lepszym rozwiązaniem byłoby podanie pary WYBRANYCH wierszy do funkcji SQL i powrotu tabeli w wyniku. – Azolin

Odpowiedz

18

Spróbuj:

select m1.`row#`, m2.`column#`, sum(m1.value*m2.value) 
from matValues m1 
join matValues m2 on m2.`row#` = m1.`column#` 
where m1.matrixID = 'mat01' and m2.matrixID = 'mat02' 
group by m1.`row#`, m2.`column#` 

Przykład here.

(Wymień 'mat01' i 'mat02' z odpowiednimi wartościami matrixID.)

+0

Wielkie dzięki, działa to jak urok :) – Azolin

+0

@ user2186956: Cieszę się, że mogłem pomóc. :) –

1

Możesz wykonać całe obliczenia w SQL. Dajesz tylko przykład z pojedynczą matrycą, która, ponieważ nie jest kwadratem, nie może być pomnożona przez siebie.

Oto pomysł:

SELECT mout.row, mout.col, SUM(m1.value*m2.value) 
FROM (select distinct row from matValues cross join 
     select distinct COL from matValues 
    ) mout left outer join 
    matValues m1 
    on m1.row = mout.row left outer join 
    matValues m2 
    on m2.col = mout.col and 
     m2.row = m1.col 
0

wiem, że to jest składnia SQL Server, ale powinien dać początek na odpowiedniej składni MySQL. Niejasna natura macierzy wydaje się dobrze radzić sobie.

with I as (
     select * from (values 
     (1,1, 1), 
     (2,2, 1), 
     (3,3, 1) 
    ) data(row,col,value) 
    ) 
    ,z_90 as (
     select * from (values 
     (1,2, 1), 
     (2,1,-1), 
     (3,3, 1) 
    ) data(row,col,value) 
    ) 
    ,xy as (
     select * from (values 
     (1,2, 1), 
     (2,1, 1), 
     (3,3, 1) 
    ) data(row,col,value) 
    ) 
    ,x_90 as (
     select * from (values 
     (1,1, 1), 
     (2,3, 1), 
     (3,2,-1) 
    ) data(row,col,value) 
    ) 
    select 
     'I * z_90' as instance, 
     a.row, 
     b.col, 
     sum(case when a.value is null then 0 else a.value end 
      * case when b.value is null then 0 else b.value end) as value 
    from I as a 
    join z_90 as b on a.col = b.row 
    group by a.row, b.col 
    union all 
    select 
     'z_90 * xy' as instance, 
     a.row, 
     b.col, 
     sum(case when a.value is null then 0 else a.value end 
      * case when b.value is null then 0 else b.value end) as value 
    from z_90 as a 
    join xy as b on a.col = b.row 
    group by a.row, b.col 
    union all 
    select 
     'z_90 * x_90' as instance, 
     a.row, 
     b.col, 
     sum(case when a.value is null then 0 else a.value end 
      * case when b.value is null then 0 else b.value end) as value 
    from z_90 as a 
    join x_90 as b on a.col = b.row 
    group by a.row, b.col 

    order by instance, a.row, b.col 

plony:

instance row   col   value 
----------- ----------- ----------- ----------- 
I * z_90 1   2   1 
I * z_90 2   1   -1 
I * z_90 3   3   1 
z_90 * x_90 1   3   1 
z_90 * x_90 2   1   -1 
z_90 * x_90 3   2   -1 
z_90 * xy 1   1   1 
z_90 * xy 2   2   -1 
z_90 * xy 3   3   1 

Jednak proponuję również sprawdzić wykonując to na karcie graficznej. NVIDIA ma dobry przykład implementacji mnożenia macierzy w przewodniku programowania C.

+0

Sprawa, w której instrukcje można oczywiście uprościć, używając składni dostawcy (np. ISNULL() lub COALESCE() dla Sql-Server itp.). –

Powiązane problemy