2011-11-14 49 views
6

Trong Oracle và MySQL, làm thế nào tôi có thể tạo ra một hàm có số lượng tham số không xác định để nó có thể được gọi là GREATEST (giá trị1, giá trị2, ...)?Số lượng đối số không xác định cho các hàm do người dùng định nghĩa SQL?

So sánh hai giá trị theo một tiêu chuẩn nhất định là khá dễ dàng nhưng chuyển giá trị "lớn hơn" để so sánh khác là điều tôi dường như không làm việc trong SQL.

Cảm ơn!

Chỉnh sửa (sau nhận xét của Mike bên dưới): Tôi đang tìm giải pháp để so sánh nhiều cột. Về mặt cụ thể, câu hỏi của tôi là cách triển khai GREATEST() như một UDF. Mã sau so sánh ba cột.

SELECT CASE WHEN CASE WHEN col_1 < col_2 THEN col_2 
       ELSE col_1 END < col_3 THEN col_3 
     ELSE CASE WHEN col_1 < col_2 THEN col_2 
       ELSE col_1 END END AS greatest 
    FROM figures; 

Rõ ràng, điều này không quy mô quá tốt. Sẽ hữu ích hơn nếu có một hàm tổng quát áp dụng cùng một phương thức so sánh lặp đi lặp lại với một danh sách các giá trị.

By SQL Ý tôi là bất kỳ sản phẩm cơ sở dữ liệu SQL nhưng tôi thích một giải pháp mà các công trình trong Oracle hoặc MySQL

+0

Đây có phải là giống như - chọn * from, order by x desc/asc Giá trị tối đa phải là giá trị đầu tiên/cuối cùng? Ngay cả trong XSLt, tôi chỉ sắp xếp mọi thứ để có được giá trị tối đa? – Mike

+0

Có lẽ bạn có nghĩa là SQL Server - SQL (không có trình độ tiếp theo) đề cập đến một ngôn ngữ, được thực hiện với các mức độ khác nhau theo các sản phẩm khác nhau. –

+2

Đây là một cách để xử lý tốt hơn câu lệnh 'case'. http://stackoverflow.com/questions/7995945/how-to-i-modify-this-t-sql-query-to-return-the-maximum-value-for-different-colum/7996068#7996068 –

Trả lời

2

Trong Oracle (trường hợp có hỗ trợ UNPIVOT)

SELECT MyID, MAX(GreatestVal) 
FROM figures 
    UNPIVOT (
      GreatestVal 
      FOR MyID 
      IN (col_1, col_2, col_3,...) 
     ); 

Oracle truy vấn là chưa được kiểm tra bởi vì Tôi không có một ví dụ tiện dụng Các chi tiết khác về trục xoay là located here và nó hoạt động giống như trục xoay của Máy chủ SQL.

MySQL tôi không chắc chắn làm thế nào để làm điều này trong MySQL nhưng có thể điều tra như tôi có cơ hội

Sau đây là SQL Server câu trả lời (trừ khi ai đó đánh bại tôi để nó ;-).):

Thực hiện nó trong UDF không đẹp vì tất cả các tham số đầu vào sẽ được YÊU CẦU trong mọi trường hợp. Nếu bạn có thể lấy đi với việc thực hiện nó như là một thủ tục lưu sẵn thì bạn có thể chỉ định các giá trị mặc định cho các tham số đầu vào và gọi nó với một số cột động. Dù bằng cách nào, bạn sẽ phải quyết định số lượng tham số đầu vào tối đa. Dưới đây là một ví dụ trong UDF trên SQL Server:

SELECT dbo.GREATESTof3(col_1, col_2, col_3) 
FROM figures; 

CREATE FUNCTION GREATESTof3(@col_1 sql_variant = null, @col_2 sql_variant = null, @col_3 sql_variant = null) 
RETURNS sql_variant 
AS 
BEGIN 
    DECLARE @GreatestVal sql_variant 
    DECLARE @ColumnVals TABLE (Candidate sql_variant) 


    INSERT INTO @ColumnVals 
    SELECT @col_1 
    UNION ALL 
    SELECT @col_2 
    UNION ALL 
    SELECT @col_3 

    SELECT @GreatestVal = MAX(Candidate) 
    FROM @ColumnVals 

    RETURN @GreatestVal 
END 

này sẽ đòi hỏi một UDF mới cho mỗi biến thể của số lượng các thông số đầu vào HOẶC tạo một mà có thể mất một số lượng lớn hơn nhưng sau đó trong cuộc gọi đến UDF bạn sẽ phải chỉ định một số giá trị cho mỗi tham số không sử dụng (null) hoặc chỉ định mặc định.

Alternatives:

này mang đến cho bạn giá trị tối đa của ba cột từ toàn bộ bảng và sẽ dễ dàng hơn để có một số năng động của cột:

SELECT MAX([Value]) AS Greatest 
FROM figures 
UNPIVOT 
(
    [Value] 
    FOR ColumnName IN ([Col_1], [Col_2], [Col_3]) 
) AS unpvt 

Giả sử bạn có một số rowid hoặc một cột khác mà bạn muốn ở đầu ra để bạn có thể nhận được giá trị lớn nhất từ ​​các cột được chỉ định cho mỗi hàng bạn có thể làm như sau:

SELECT RowID, MAX([Value]) AS Greatest 
FROM figures 
UNPIVOT 
(
    [Value] 
    FOR ColumnName IN ([Col_1], [Col_2], [Col_3]) 
) AS unpvt 
GROUP BY RowID 
0

Một tùy chọn SQL Server khác (không chắc chắn nó sẽ chuyển thành MySQL/Oracle như thế nào).

Tôi đã làm điều này với một danh sách các ID số nguyên trước khi mà tôi đưa vào một danh sách dấu phẩy phân cách và làm thức ăn cho một chức năng để có được lớn nhất:

CREATE Function [dbo].[GreatestFromList] 
(@ListOfValues VARCHAR(8000)) 

RETURNS INT 

AS 

BEGIN 

DECLARE @ListOfValuesTable TABLE (ValueColumn INT) 

    DECLARE @spot1 SMALLINT, @str1 VARCHAR(8000) 

    WHILE @ListOfValues <> '' 
    BEGIN 
     SET @spot1 = CHARINDEX(',', @ListOfValues) 
     IF @spot1>0 
      BEGIN 
       SET @str1 = LEFT(@ListOfValues, @spot1-1) 
       SET @ListOfValues = RIGHT(@ListOfValues, LEN(@ListOfValues)[email protected]) 
      END 
     ELSE 
      BEGIN 
       SET @str1 = @ListOfValues 
       SET @ListOfValues = '' 
      END 
     INSERT INTO @ListOfValuesTable (ValueColumn) VALUES(convert(int, @str1)) 
    END 

DECLARE @GreatestValue INT 

SELECT @GreatestValue = SELECT MAX(ValueColumn) FROM @ListOfValuesTable 

RETURN @GreatestValue 

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