2016-12-01 17 views
7

Tôi có một loại MyType quy định như sau:Oracle SQL: sử dụng chức năng LAG với người dùng định nghĩa kiểu trả về "kiểu dữ liệu không phù hợp"

create or replace type MyType as varray(20000) of number(18); 

Và một MyTable bảng quy định như sau:

create table MyTable (
    id  number(18) primary key 
    ,widgets MyType 
) 

Tôi đang cố gắng chọn các tiện ích con cho mỗi hàng và hàng trước đó trong MyTable bằng cách sử dụng SQL sau:

select t.id 
     ,lag(t.widgets,1) over (order by t.id) as widgets_previous 
from MyTable t 
order by t.id; 

và tôi nhận được phản hồi:

ORA-00932: inconsistent datatypes: expected - got MYSCHEMA.MYTYPE 

Nếu tôi chạy cùng một truy vấn bằng cách sử dụng cột loại varchar hoặc số thay vì MyType hoạt động tốt.

Loại cột trong hàng hiện tại và hàng trước đó của cột phải giống nhau vì vậy tôi chỉ có thể giả định nó là thứ liên quan đến loại do người dùng xác định.

Tôi có cần phải làm điều gì đó đặc biệt để sử dụng LAG với loại do người dùng xác định hay không LAG không hỗ trợ các loại do người dùng xác định? Nếu sau này, có bất kỳ chức năng tiện ích nào khác có thể cung cấp cùng một chức năng hoặc tôi có cần thực hiện một phép tự kết nối truyền thống để đạt được điều tương tự không?

+0

tôi không thể kiểm tra điều này bản thân mình ngay bây giờ, không may, nhưng những gì xảy ra nếu bạn làm: 'lag (t.widgets, 1, dàn diễn viên (null như MyType)) qua (thứ tự bởi t.id) '? – Boneist

+0

@Boneist - Tôi e rằng tôi vẫn nhận được phần ORA-00932 mặc dù, một ý tưởng tuyệt vời! – Pancho

+0

Một cách khác để sử dụng bảng lồng nhau là tạo bảng và lưu trữ dữ liệu của bạn một cách rõ ràng, sau đó có một khóa từ bảng mới quay lại mytable (và sau đó sử dụng SQL để so sánh các tập dữ liệu). Nếu không, tự tham gia có lẽ là cách dễ nhất để thực hiện việc này (ví dụ: tìm id của hàng trước đó và tham gia vào id hiện tại) – Boneist

Trả lời

2

Sau khi đọc bài trên, chúng tôi đã chọn sau như là phương pháp hiệu quả nhất để đạt được những gì tôi cần:

select curr.id 
     ,curr.widgets as widgets 
     ,prev.widgets as previous_widgets 
from (select a.id          
      ,a.widgets 
      ,lag(a.id,1) over (order by a.id) as previous_id 
     from mytable a 
    ) curr 
    left join mytable prev on (prev.id = curr.previous_id) 
order by curr.id 

tức. một lag/self join hybrid sử dụng độ trễ trên một trường số mà nó không phàn nàn về việc xác định điều kiện kết nối. Nó khá gọn gàng Tôi nghĩ và tôi nhận được bộ sưu tập của tôi như mong muốn. Nhờ tất cả mọi người cho đầu vào cực kỳ hữu ích.

1

Bạn có thể sử dụng lag với UDT. Vấn đề là varray

Điều này có cung cấp cho bạn kết quả không?

select t.id 
     ,lag(
       (select listagg(column_value, ',') within group (order by column_value) 
        from table(t.widgets)) 
      ,1) over (order by t.id) as widgets_previous 
from MyTable t 
order by t.id; 
+0

Xin chào @Kacper thật đáng buồn là sự cố kết hợp của tôi: Phần 1: Tôi không thể sử dụng lồng nhau bảng trên varrays (mặc dù tôi thực sự muốn) bởi vì tại 12c Oracle xuất hiện không hỗ trợ các bảng lồng nhau như cột trong bảng tạm thời (ORA-14457). Phần 2: Tôi quen thuộc với listagg và cho một trường hợp sử dụng khác, nó có thể hoạt động tuy nhiên tôi đang theo dõi các bộ sưu tập để tôi có thể sử dụng các toán tử "multiset" Oracle để thực hiện các so sánh khác nhau. - cảm ơn rất nhiều vì đầu vào của bạn! – Pancho

+1

'chọn t.id, t2.widgets từ MyTable t bên ngoài bên trái tham gia MyTable t2 trên (t.id = t2.id + 1);' điều này không giải quyết được vấn đề của bạn? – Kacper

+0

Hi @Kacper cách tiếp cận này là khái niệm tương tự như những gì tôi đã đi cho dưới đây tuy nhiên nó dựa trên giá trị id liên tiếp mà không thể được đảm bảo trong kịch bản của tôi :) – Pancho

0

Bạn có thể thử một cái gì đó như:

SQL> create or replace type TestType as varray(20000) of number(18); 
Type created. 
SQL> create table TestTable (
    id  number(18) primary key 
    ,widgets TestType 
) 
Table created. 
SQL> delete from testtable 
0 rows deleted. 
SQL> insert into TestTable values (1, TestType(1,2,3,4)) 
1 row created. 
SQL> insert into TestTable values (2, TestType(5,6,7)) 
1 row created. 
SQL> insert into TestTable values (3, TestType()) 
1 row created. 
SQL> insert into TestTable values (4,null) 
1 row created. 
SQL> commit 
Commit complete. 

SQL> -- show all data with widgets 
SQL> select t.id, w.column_value as widget_ids 
from testtable t, table(t.widgets) w 

     ID WIDGET_IDS 
---------- ---------- 
     1   1 
     1   2 
     1   3 
     1   4 
     2   5 
     2   6 
     2   7 

7 rows selected. 
SQL> -- show with lag function 
SQL> select t.id, lag(w.column_value, 1) over (order by t.id) as widgets_previous 
from testtable t, table(t.widgets) w 

     ID WIDGETS_PREVIOUS 
---------- ---------------- 
     1     
     1    1 
     1    2 
     1    3 
     2    4 
     2    5 
     2    6 

7 rows selected. 
+0

hi @tbone - những gì bạn đang quay trở lại không hoàn toàn là những gì tôi sau. Bạn đã chèn 4 hàng để chọn tương tự như vậy sẽ trả về 4 hàng, hàng 1 giữ bộ sưu tập hàng 1 và null cho bộ sưu tập trước đó, hàng 2 giữ bộ sưu tập hàng 2 và bộ sưu tập hàng 1 và cứ thế ... cảm ơn cho đầu vào! – Pancho

+0

Ah, ok, tôi hiểu lầm những gì bạn đang tìm kiếm. Tham gia bàn với chính nó như bạn đã đề xuất có vẻ giống như cách để đi. – tbone

Các vấn đề liên quan