2011-01-07 51 views
6

Tôi có một bảng có nhiều cột và cột loại.Oracle: Tìm Cột chỉ có giá trị rỗng

Một số cột dường như luôn trống cho một loại cụ thể.

Tôi muốn tạo chế độ xem cho từng loại và chỉ hiển thị các cột có liên quan cho từng loại. Làm việc với giả định rằng nếu một cột có giá trị null chỉ cho một loại cụ thể, thì các cột đó không phải là một phần của khung nhìn, làm thế nào bạn có thể tìm ra các truy vấn đó?

Có CHỌN [ColumnName] FROM [bảng] WHERE [columnValues] ĐƯỢC TẤT CẢ [null]

Tôi biết tôi hoàn toàn làm cho nó tất cả lên trên ... Tôi chỉ cố gắng để có được những ý tưởng băng qua. Cảm ơn bạn trước!

+0

Vì vậy, nếu bạn có 50 cột, và 10 trong số đó chứa các giá trị chỉ NULL, bạn muốn có một truy vấn mà sẽ chỉ trở lại 40 cột thực sự có dữ liệu? Và có lẽ nếu một trong 10 người khác mua lại một giá trị, truy vấn của bạn sau đó sẽ trả lại 41 cột? – MartW

+0

Có vẻ như bạn có các loại "bản ghi" hoặc "loại" khác nhau trong cùng một bảng, nơi bạn muốn có một chế độ xem riêng biệt cho từng loại. Có cột nào xác định "loại" bản ghi không? –

+0

Vâng, đó chính xác là @CodeByMoonlight. –

Trả lời

0

Một cái gì đó như thế này?

SELECT column1, column2, column3 -- and so on 
FROM tableA 
WHERE columnX IS NULL 
AND columnY IS NULL 
AND columnZ IS NULL; 

Rõ ràng, bạn có thể sử dụng điều đó trong tuyên bố CREATE VIEW... nếu bạn muốn.

+1

Bên cạnh thực tế là điều này không chọn cột, điều này thậm chí không cho biết khi nào "[columnValues] là ALL [null]". Điều này sẽ chọn một loạt các hàng mà một số cột nhất định (cho hàng đó) là null - đây không phải là thông tin hữu ích để xác định các cột nào là tất cả null – Gerrat

+0

@Gerrat, Oracle không có khái niệm về từ khóa 'ALL' trong mệnh đề điều kiện của 'SELECT' (xem http://download.oracle.com/docs/cd/B13789_01/server.101/b10759/conditions.htm#g1077361). Nếu @Jorge muốn tạo các khung nhìn khác nhau cho mỗi 'loại', anh ta cần phải xác định xem 'loại' có dựa trên một phân biệt đối xử cột hay bởi sự hiện diện của các cột rỗng cụ thể cho tất cả các bản ghi loại đó. Anh ta có vẻ bối rối hai phương pháp. –

+2

@BQ: Đây không phải là từ khóa 'ALL' huyền bí. Đó là về những gì OP đang cố gắng để có được. Tôi nghĩ nếu bạn đọc lại những gì anh ta đang tìm kiếm, thì rõ ràng từ ngữ cảnh mà sau này anh ta nói: "Cho tôi tên cột của cột mà MỌI hàng của cột đó là null, cho một kiểu cụ thể." ... Vì vậy, sql của bạn trả về hàng thay vì tên cột, và các hàng nó cho không thực sự làm cho chúng ta gần gũi hơn để biết nếu hàng EVERY cho cột đó là NULL. Nó chỉ đơn giản trả về các hàng trong đó (mỗi cột trong một tập hợp các cột) là NULL – Gerrat

0

Sau khi xem nhận xét của @Gerrat và @ BQ, tôi thouht tôi có thể nhận được các chi tiết tôi cần theo cách sau: Tôi có một bảng kế thừa có N loại khác nhau. Tất cả các loại chia sẻ cột và có các cột độc quyền.

Tôi có thể tạo chế độ xem cho từng loại với tất cả các cột, sau đó sử dụng all_tab_columns để nhận tất cả các tên cột trong đó "num_nulls" nhỏ hơn tổng số hàng cho loại cụ thể đó.

Từ đó phải dễ dàng thu thập các cột được sử dụng cho từng loại và tạo chế độ xem.

Suy nghĩ?

2
select 
    count(col_1), 
    count(col_2), 
    count(col_3) 
from 
    <table> 

lợi nhuận bao nhiêu hồ sơ cho mỗi cột có một giá trị khác null (ít nhất là trong Oracle, đó là.)

Ví dụ

drop table tq84_count_nulls; 

create table tq84_count_nulls (
    col_1 varchar(50), 
    col_2 number, 
    col_3 date 
); 

insert into tq84_count_nulls values (null, null, null); 
insert into tq84_count_nulls values ('xx', null, null); 
insert into tq84_count_nulls values (null, 42, null); 
insert into tq84_count_nulls values ('yy', 12, null); 

select 
    count(col_1), 
    count(col_2), 
    count(col_3) 
from 
    tq84_count_nulls; 

lợi nhuận

COUNT(COL_1) COUNT(COL_2) COUNT(COL_3) 
------------ ------------ ------------ 
      2   2   0 

chỉ ra rằng col_3 chỉ bao gồm các giá trị rỗng.

Ý tưởng này sau đó có thể được sử dụng để tạo chế độ xem mong muốn.

Bảng bây giờ cũng cần * GROUP_ID *:

drop table tq84_count_nulls; 
create table tq84_count_nulls (
    col_1 varchar(50), 
    col_2 number, 
    col_3 date, 
    group_id varchar(2) 
); 

insert into tq84_count_nulls values (null, null, null, 'a'); 
insert into tq84_count_nulls values ('xx', null, null, 'a'); 
insert into tq84_count_nulls values (null, 42, null, 'a'); 
insert into tq84_count_nulls values ('yy', 12, null, 'a'); 

insert into tq84_count_nulls values (null, null, null, 'b'); 
insert into tq84_count_nulls values (null, null, null, 'b'); 
insert into tq84_count_nulls values (null, 42, null, 'b'); 
insert into tq84_count_nulls values (null, 12, null, 'b'); 




create or replace view nulls_per_type as 
with n as (
    select 
    count(col_1) col_1_count, 
    count(col_2) col_2_count, 
    count(col_3) col_3_count, 
    group_id 
    from 
    tq84_count_nulls 
    group by 
    group_id 
), 
o as (
select case col_1_count when 0 then 'COL_1 is always 0 for ' || group_id else null end u from n union all 
select case col_2_count when 0 then 'COL_2 is always 0 for ' || group_id else null end u from n union all 
select case col_3_count when 0 then 'COL_3 is always 0 for ' || group_id else null end u from n 
) 
select * from o where u is not null; 

nào, khi lợi nhuận được chọn:

select * from nulls_per_type; 

COL_1 is always 0 for b 
COL_3 is always 0 for a 
COL_3 is always 0 for b 
+0

Đó là tiêu chuẩn SQL, không chỉ Oracle. Bạn cũng có thể làm: 'SELECT COUNT (col_1), COUNT (col_2), COUNT (col_3) [...] FROM SomeTable CÓ COUNT (*)> 0 AND (COUNT (col_1) = 0 HOẶC COUNT (col_2) = 0 HOẶC COUNT (col_3) = 0'. Điều đó bỏ qua tất cả các bảng trống và chỉ trả về bất cứ thứ gì nếu ít nhất một trong các thử nghiệm các cột chỉ có null trong số đó –

+0

Bảng của tôi có hơn 300 cột, tôi không muốn đếm 300 lần trong mỗi 300. –

+0

Tôi không muốn bất kỳ bản ghi nào từ bảng gốc của tôi. bảng của tôi, nơi tất cả các hồ sơ cho một loại cụ thể chỉ có giá trị null –

0

Tôi nghĩ rằng bạn có thể giải quyết việc này bằng lập trình meta. Sử dụng con trỏ để lặp qua từng loại và cột và sử dụng 'không tồn tại' để kiểm tra xem cột có trống không. Ví dụ:

CREATE TABLE result_table (type VARCHAR(50), column VARCHAR(50)) 

CURSOR c IS 
    SELECT COLUMN_NAME FROM ALL_TAB_COLS WHERE TABLE_NAME = &table_name; 

CURSOR ct IS 
    SELECT DISTINCT type_name FROM &table_name; 

BEGIN 

FOR t in ct 
LOOP 
    FOR r in c 
    LOOP 
     --If you're confused about how this works, replace 'EXECUTE IMMEDIATE' 
     --with print or something and look at the output 
     EXECUTE IMMEDIATE 
      'INSERT INTO result_table SELECT ''' || 
       t.type_name || ''', ''' || r.COLUMN_NAME || 
       ''' FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM ' || 
       &table_name || ' WHERE t.type_name = ''' || t.type_name || 
       ''' AND ' || r.COLUMN_NAME || ' IS NOT NULL);'; 
    END LOOP 
END LOOP 

SELECT * FROM result_table 

Xin lỗi nếu có lỗi trong cú pháp ở đâu đó, tôi không có gì để kiểm tra điều này.

9
SELECT t.column_name 
FROM user_tab_columns t 
WHERE t.nullable = 'Y' 
     AND t.table_name = 'YOUR_TABLE_NAME' 
     AND t.num_distinct = 0 
+1

Tôi đã phải chạy các số liệu thống kê đầu tiên 'DBMS_STATS.gather_database_stats();' và sau đó điều này làm việc như một say mê! Cảm ơn;) – nathanvda

0

CHỌN tablecolumn, tablecolumn2, ... TỪ TABLENAME ĐÂU cột IS NOT NULL

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