2012-03-10 48 views
6

bảng My hợp--Cách tính trung bình của một cột và sau đó bao gồm nó trong một truy vấn chọn trong oracle?

create table mobile 
(
    id integer, 
    m_name varchar(20), 
    cost integer 
) 

và các giá trị là -

insert into mobile values(10,'NOkia',100); 
insert into mobile values(11,'Samsung',150); 
insert into mobile values(12,'Sony',120); 

tôi biết làm thế nào để tính toán bình quân trên chi phí cột, mã của tôi hợp--

select avg(cost) from mobile; 

và kết quả là

Nhưng iw ant để tính toán trung bình và sau đó cũng cho thấy difference.I đã có thể này, nhưng, tôi không thể để thêm cột trung bình trong query-- chọn

Mã của tôi là ---

SELECT id, m_name as "Mobile Name", cost as Price,avg(cost) as Average, 
cost-(select avg(cost) from mobile) as Difference FROM mobile 
group by id,m_name,cost; 

và đầu ra là -

id  Mobile Name Price Average Difference 
10  Nokia   100 100  -23 
11  Samsung  150 150  27 
12  Sony   120 120  -3 

những gì tôi muốn là để sửa chữa cột trung bình này .. tôi muốn này ---

id  Mobile Name Price Average Difference 
10  Nokia  100  123  -23 
11  Samsung  150  123  27 
12  Sony  120  123  -3 

xin vui lòng giúp đỡ ...

+3

+1 để cung cấp 'tạo bảng' và dữ liệu mẫu dưới dạng' chèn', nhưng đó không phải là cú pháp Oracle hợp lệ (Oracle không có 'bigint' hoặc' int). Và con số không nên được đặt trong dấu nháy đơn! –

+1

@JustinPihony, bạn có thể sử dụng '[faq]', [faq], '[ask]', [yêu cầu] vv thay vào đó, xem http://stackoverflow.com/editing-help#comment-formatting – Ben

+0

@Ben Cảm ơn, Tôi đã có ý nghĩa để xem xét định dạng nhận xét. Nhiều đánh giá cao. –

Trả lời

9

nhóm của bạn bởi những gì là tập hợp trung bình của bạn, và nó được nhóm bởi toàn bộ bảng (Tôi giả sử bạn đã làm điều này để cho phép lựa chọn cho tất cả mọi thứ) Chỉ cần di chuyển avg của bạn vào một truy vấn con khác, loại bỏ các nhóm bao quát bởi và rằng nên giải quyết nó.

SELECT id, m_name AS "Mobile Name", cost AS Price, 
    (SELECT AVG(cost) FROM mobile) AS Average, 
    cost-(SELECT AVG(cost) FROM mobile) AS Difference 
FROM mobile; 

Khi bạn chạy SELECT AVG(cost) tuyên bố cơ bản nó là một cách tự nhiên nhóm bởi các cột được chỉ định (chi phí trong trường hợp này) vì đó là những gì bạn đang yêu cầu. Tôi khuyên bạn nên đọc thêm trên GROUP BYaggregates để hiểu rõ hơn về khái niệm. Điều đó sẽ giúp bạn nhiều hơn chỉ là một giải pháp đơn giản.

UPDATE:

Câu trả lời dưới đây là thực sự từ câu trả lời của David. Nó sử dụng các chức năng phân tích. Về cơ bản, những gì đang xảy ra là trên mỗi cuộc gọi AVG, bạn đang nói cho động cơ những gì để sử dụng cho các chức năng (trong trường hợp này, không có gì). Bạn có thể tìm thấy một ghi chú phong phú về các chức năng phân tích herehere và nhiều tính năng khác với google về vấn đề này.

SELECT id, m_name AS "Mobile Name" cost AS Price, AVG(cost) OVER() AS Average, 
    cost - AVG(cost) OVER () AS Difference 
    FROM mobile 

Tuy nhiên, nếu công cụ SQL của bạn cho phép biến, bạn có thể dễ dàng thực hiện câu trả lời dưới đây.Tôi thực sự thích điều này cho khả năng bảo trì/dễ đọc trong tương lai. Lý do là một biến có tên tốt có thể mô tả rất rõ đối với người đọc trong tương lai của mã, so với hàm phân tích đòi hỏi nhiều công việc hơn một chút để đọc (đặc biệt là nếu bạn không hiểu hàm over).

Ngoài ra, giải pháp này sao chép cùng một truy vấn hai lần, do đó, nó có thể là giá trị lưu trữ trung bình của bạn trong một biến SQL. Sau đó, bạn ca thay đổi tuyên bố của bạn chỉ đơn giản là sử dụng trung bình toàn cầu

Đây là các biến trong SQL Server (bạn sẽ phải thích ứng với nó ví dụ của riêng bạn của SQL)

DECLARE @my_avg INT; 
SELECT @my_avg = AVG(cost) FROM Mobile; 

    SELECT id, m_name AS "Mobile Name", cost AS Price, 
     @my_avg AS Average, [email protected]_avg AS Difference 
    FROM mobile; 

Giải pháp này sẽ đọc rất nhiều sạch hơn đối với độc giả tương lai của SQL của bạn, quá

+0

Tôi khá chắc rằng truy vấn của David ít nhất là hiệu quả và không yêu cầu sử dụng khối PL/SQL yêu cầu bạn đưa kết quả của SELECT vào biến - nó sẽ không được hiển thị theo cách bạn đã viết (thực ra Tôi nghĩ rằng nó thậm chí sẽ không chạy). Và bên cạnh truy vấn trùng lặp sẽ chỉ được chạy một lần bởi Oracle. Tôi chắc rằng trình tối ưu hóa đủ thông minh để phát hiện điều đó. –

+0

Tôi đánh giá cao sự giải thích của bạn, nhưng khối PL/SQL chỉ đơn giản là sai. Cách tiếp cận đó sẽ không bao giờ làm việc trong Oracle. Nếu bạn không muốn lặp lại truy vấn avg(), hãy sử dụng phương pháp tiếp cận với hàm phân tích hoặc giải pháp nối chéo. –

+0

Điều đó không làm cho PL/SQL đúng. Nó vẫn còn * sai * và ** sẽ không chạy ** –

0

thử

SELECT id, m_name as "Mobile Name", cost as Price,(select avg(cost) from mobile) as Average), 
cost-(select avg(cost) from mobile) as Difference FROM mobile 
group by id,m_name,cost; 

nếu truy vấn của bạn là quá đắt như vậy thả cho tôi một khen sau đó tôi sẽ cải thiện nó.

2

Thay đổi đơn giản nhất là thay đổi avg(cost) as Average thành (select avg(cost) from mobile) as Average. Điều này cũng có nghĩa là bạn sẽ không cần mệnh đề GROUP BY nữa (vì nó không làm những gì bạn thực sự muốn):

SELECT id, 
     m_name AS "Mobile Name", 
     cost AS "Price", 
     (SELECT AVG(cost) FROM mobile) AS "Average", 
     cost - (SELECT AVG(cost) FROM mobile) AS "Difference" 
    FROM mobile 
; 
0

một trong những lần hiếm hoi một CROSS JOIN được áp dụng:

WITH avgcost as (select round(avg(cost)) as Average from mobile) 
SELECT id, m_name as "Mobile Name", cost as Price, Average, 
cost-Average as Difference 
FROM mobile cross join avgcost 

nào sẽ cho kết quả:

ID Mobile Name PRICE AVERAGE DIFFERENCE 
10 NOkia  100  123  -23 
11 Samsung  150  123  27 
12 Sony  120  123  -3 
11

Vì bạn đang sử dụng Oracle, bạn sẽ có thể sử dụng AVG() như là một phân tích (cửa sổ) chức năng:

SELECT id, m_name AS "Mobile Name" cost AS Price, AVG(cost) OVER() AS Average 
    , cost - AVG(cost) OVER () AS Difference 
    FROM mobile 

Không cần truy vấn con hay GROUP BY.

+1

+ 1 sử dụng tốt chức năng phân tích :) –

0
select pid, name, price as actualcost, 
     AVERAGE = (select AVG(price) from Part_Master), 
     price - (select AVG(price) as diff from Part_Master) AS COST_DIFF 
from Part_Master 
Các vấn đề liên quan