คุณจะคืนค่า 1 ค่าต่อแถวของจำนวนคอลัมน์สูงสุดได้อย่างไร:
TableName
[Number, Date1, Date2, Date3, Cost]
ฉันต้องการส่งคืนสิ่งนี้:
[Number, Most_Recent_Date, Cost]
แบบสอบถาม?
คุณจะคืนค่า 1 ค่าต่อแถวของจำนวนคอลัมน์สูงสุดได้อย่างไร:
TableName
[Number, Date1, Date2, Date3, Cost]
ฉันต้องการส่งคืนสิ่งนี้:
[Number, Most_Recent_Date, Cost]
แบบสอบถาม?
คำตอบ:
คุณสามารถใช้คำสั่ง CASE:
SELECT
CASE
WHEN Date1 >= Date2 AND Date1 >= Date3 THEN Date1
WHEN Date2 >= Date1 AND Date2 >= Date3 THEN Date2
WHEN Date3 >= Date1 AND Date3 >= Date2 THEN Date3
ELSE Date1
END AS MostRecentDate
[สำหรับ Microsoft SQL Server 2008และสูงกว่าคุณอาจพิจารณาคำตอบที่ง่ายกว่าของ Sven ด้านล่าง]
นี่เป็นอีกวิธีที่ดีสำหรับการMax
ใช้ T-SQL และ SQL Server
SELECT [Other Fields],
(SELECT Max(v)
FROM (VALUES (date1), (date2), (date3),...) AS value(v)) as [MaxDate]
FROM [YourTableName]
หากคุณใช้ MySQL คุณสามารถใช้
SELECT GREATEST(col1, col2 ...) FROM table
มีอีก 3 วิธีที่UNPIVOT
(1) เร็วที่สุดตามมาด้วย Unspivot จำลอง (3) ซึ่งช้ากว่า (1) มาก แต่ยังเร็วกว่า (2)
CREATE TABLE dates
(
number INT PRIMARY KEY ,
date1 DATETIME ,
date2 DATETIME ,
date3 DATETIME ,
cost INT
)
INSERT INTO dates
VALUES ( 1, '1/1/2008', '2/4/2008', '3/1/2008', 10 )
INSERT INTO dates
VALUES ( 2, '1/2/2008', '2/3/2008', '3/3/2008', 20 )
INSERT INTO dates
VALUES ( 3, '1/3/2008', '2/2/2008', '3/2/2008', 30 )
INSERT INTO dates
VALUES ( 4, '1/4/2008', '2/1/2008', '3/4/2008', 40 )
GO
UNPIVOT
)SELECT number ,
MAX(dDate) maxDate ,
cost
FROM dates UNPIVOT ( dDate FOR nDate IN ( Date1, Date2,
Date3 ) ) as u
GROUP BY number ,
cost
GO
SELECT number ,
( SELECT MAX(dDate) maxDate
FROM ( SELECT d.date1 AS dDate
UNION
SELECT d.date2
UNION
SELECT d.date3
) a
) MaxDate ,
Cost
FROM dates d
GO
UNPIVOT
);WITH maxD
AS ( SELECT number ,
MAX(CASE rn
WHEN 1 THEN Date1
WHEN 2 THEN date2
ELSE date3
END) AS maxDate
FROM dates a
CROSS JOIN ( SELECT 1 AS rn
UNION
SELECT 2
UNION
SELECT 3
) b
GROUP BY Number
)
SELECT dates.number ,
maxD.maxDate ,
dates.cost
FROM dates
INNER JOIN MaxD ON dates.number = maxD.number
GO
DROP TABLE dates
GO
หนึ่งในสองตัวอย่างด้านล่างนี้จะใช้งานได้:
SELECT MAX(date_columns) AS max_date
FROM ( (SELECT date1 AS date_columns
FROM data_table )
UNION
( SELECT date2 AS date_columns
FROM data_table
)
UNION
( SELECT date3 AS date_columns
FROM data_table
)
) AS date_query
ประการที่สองคือส่วนเสริมของคำตอบของ lassevk
SELECT MAX(MostRecentDate)
FROM ( SELECT CASE WHEN date1 >= date2
AND date1 >= date3 THEN date1
WHEN date2 >= date1
AND date2 >= date3 THEN date2
WHEN date3 >= date1
AND date3 >= date2 THEN date3
ELSE date1
END AS MostRecentDate
FROM data_table
) AS date_query
สำหรับ T-SQL (MSSQL 2008+)
SELECT
(SELECT
MAX(MyMaxName)
FROM ( VALUES
(MAX(Field1)),
(MAX(Field2))
) MyAlias(MyMaxName)
)
FROM MyTable1
DECLARE @TableName TABLE (Number INT, Date1 DATETIME, Date2 DATETIME, Date3 DATETIME, Cost MONEY)
INSERT INTO @TableName
SELECT 1, '20000101', '20010101','20020101',100 UNION ALL
SELECT 2, '20000101', '19900101','19980101',99
SELECT Number,
Cost ,
(SELECT MAX([Date])
FROM (SELECT Date1 AS [Date]
UNION ALL
SELECT Date2
UNION ALL
SELECT Date3
)
D
)
[Most Recent Date]
FROM @TableName
ฟังก์ชันสเกลาร์ทำให้เกิดปัญหาประสิทธิภาพการทำงานทุกประเภทดังนั้นจึงเป็นการดีกว่าที่จะรวมตรรกะไว้ในฟังก์ชันที่มีค่าในตารางแบบอินไลน์หากเป็นไปได้ นี่คือฟังก์ชั่นที่ฉันใช้เพื่อแทนที่บางฟังก์ชั่นที่ผู้ใช้กำหนดซึ่งเลือกวันที่ต่ำสุด / สูงสุดจากรายการของไม่เกินสิบวัน เมื่อทดสอบบนชุดข้อมูลของฉัน 1 ล้านแถวฟังก์ชัน Scalar ใช้เวลามากกว่า 15 นาทีก่อนที่ฉันจะฆ่าแบบสอบถาม Inline TVF ใช้เวลา 1 นาทีซึ่งเป็นระยะเวลาเท่ากับการเลือกชุดผลลัพธ์ลงในตารางชั่วคราว เมื่อต้องการใช้การเรียกนี้ฟังก์ชันจากแบบสอบถามย่อยใน SELECT หรือ CROSS ใช้
CREATE FUNCTION dbo.Get_Min_Max_Date
(
@Date1 datetime,
@Date2 datetime,
@Date3 datetime,
@Date4 datetime,
@Date5 datetime,
@Date6 datetime,
@Date7 datetime,
@Date8 datetime,
@Date9 datetime,
@Date10 datetime
)
RETURNS TABLE
AS
RETURN
(
SELECT Max(DateValue) Max_Date,
Min(DateValue) Min_Date
FROM (
VALUES (@Date1),
(@Date2),
(@Date3),
(@Date4),
(@Date5),
(@Date6),
(@Date7),
(@Date8),
(@Date9),
(@Date10)
) AS Dates(DateValue)
)
SELECT
CASE
WHEN Date1 >= Date2 AND Date1 >= Date3 THEN Date1
WHEN Date2 >= Date3 THEN Date2
ELSE Date3
END AS MostRecentDate
นี่เป็นเรื่องง่ายที่จะเขียนออกมาเล็กน้อยและข้ามขั้นตอนการประเมินผลเนื่องจากคำสั่ง case ถูกประเมินตามลำดับ
น่าเสียดายที่คำตอบของ Lasseแม้ว่าจะดูเหมือนชัดเจน แต่ก็มีข้อบกพร่องที่สำคัญ ไม่สามารถจัดการค่า NULL ได้ ค่า NULL ใด ๆ ที่เป็นผลลัพธ์ใน Date1 จะถูกส่งคืน น่าเสียดายที่ความพยายามใด ๆ ในการแก้ไขปัญหานั้นมีแนวโน้มที่จะยุ่งเหยิงอย่างยิ่งและไม่ได้ปรับขนาดเป็น 4 หรือมากกว่านั้นอย่างมาก
คำตอบแรกของ databyssดู (และ) ดี อย่างไรก็ตามมันไม่ชัดเจนว่าคำตอบจะประมาณค่าได้ 3 ค่าจากการรวมหลายตารางแทนค่า 3 อย่างง่ายจากตารางเดียวหรือไม่ ฉันต้องการหลีกเลี่ยงการเปลี่ยนแบบสอบถามดังกล่าวเป็นแบบสอบถามย่อยเพื่อให้ได้สูงสุด 3 คอลัมน์และฉันค่อนข้างมั่นใจว่าความคิดที่ยอดเยี่ยมของ databyss สามารถทำความสะอาดได้เล็กน้อย
ดังนั้นหากไม่มีความกังวลใจเพิ่มเติมนี่คือคำตอบของฉัน (มาจากความคิดของ databyss)
มันใช้ cross-joins เลือกค่าคงที่เพื่อจำลองผลกระทบของการเข้าร่วมหลายตาราง สิ่งสำคัญที่ควรทราบคือนามแฝงที่จำเป็นทั้งหมดดำเนินการอย่างถูกต้อง (ซึ่งไม่ได้เป็นทุกกรณี) และสิ่งนี้ทำให้รูปแบบค่อนข้างเรียบง่ายและสามารถปรับขนาดได้ผ่านคอลัมน์เพิ่มเติม
DECLARE @v1 INT ,
@v2 INT ,
@v3 INT
--SET @v1 = 1 --Comment out SET statements to experiment with
--various combinations of NULL values
SET @v2 = 2
SET @v3 = 3
SELECT ( SELECT MAX(Vals)
FROM ( SELECT v1 AS Vals
UNION
SELECT v2
UNION
SELECT v3
) tmp
WHERE Vals IS NOT NULL -- This eliminates NULL warning
) AS MaxVal
FROM ( SELECT @v1 AS v1
) t1
CROSS JOIN ( SELECT @v2 AS v2
) t2
CROSS JOIN ( SELECT @v3 AS v3
) t3
ปัญหา: เลือกค่าอัตราขั้นต่ำที่กำหนดให้กับเอนทิตีข้อกำหนด: อัตราเอเจนต์สามารถเป็นโมฆะ
[MinRateValue] =
CASE
WHEN ISNULL(FitchRating.RatingValue, 100) < = ISNULL(MoodyRating.RatingValue, 99)
AND ISNULL(FitchRating.RatingValue, 100) < = ISNULL(StandardPoorsRating.RatingValue, 99)
THEN FitchgAgency.RatingAgencyName
WHEN ISNULL(MoodyRating.RatingValue, 100) < = ISNULL(StandardPoorsRating.RatingValue , 99)
THEN MoodyAgency.RatingAgencyName
ELSE ISNULL(StandardPoorsRating.RatingValue, 'N/A')
END
หากคุณใช้ SQL Server 2005 คุณสามารถใช้คุณสมบัติ UNPIVOT นี่คือตัวอย่างที่สมบูรณ์:
create table dates
(
number int,
date1 datetime,
date2 datetime,
date3 datetime
)
insert into dates values (1, '1/1/2008', '2/4/2008', '3/1/2008')
insert into dates values (1, '1/2/2008', '2/3/2008', '3/3/2008')
insert into dates values (1, '1/3/2008', '2/2/2008', '3/2/2008')
insert into dates values (1, '1/4/2008', '2/1/2008', '3/4/2008')
select max(dateMaxes)
from (
select
(select max(date1) from dates) date1max,
(select max(date2) from dates) date2max,
(select max(date3) from dates) date3max
) myTable
unpivot (dateMaxes For fieldName In (date1max, date2max, date3max)) as tblPivot
drop table dates
ใช้ CROSS APPLY (สำหรับปี 2005+) ....
SELECT MostRecentDate
FROM SourceTable
CROSS APPLY (SELECT MAX(d) MostRecentDate FROM (VALUES (Date1), (Date2), (Date3)) AS a(d)) md
จาก SQL Server 2012 เราสามารถใช้IIF
DECLARE @Date1 DATE='2014-07-03';
DECLARE @Date2 DATE='2014-07-04';
DECLARE @Date3 DATE='2014-07-05';
SELECT IIF(@Date1>@Date2,
IIF(@Date1>@Date3,@Date1,@Date3),
IIF(@Date2>@Date3,@Date2,@Date3)) AS MostRecentDate
DECLARE @Date1 DATE='2014-08-01'; DECLARE @Date2 DATE=null; DECLARE @Date3 DATE='2014-07-05'; /*this gets returned*/
select IIF(@Date1 > @Date2 or @Date2 is null, IIF(@Date1 > @Date3 or @Date3 is null, @Date1, @Date3), IIF(@Date2 > @Date3 or @Date3 is null, @Date2, @Date3)) as MostRecentDate
โปรดลองใช้UNPIVOT
:
SELECT MAX(MaxDt) MaxDt
FROM tbl
UNPIVOT
(MaxDt FOR E IN
(Date1, Date2, Date3)
)AS unpvt;
ฉันชอบวิธีแก้ปัญหาเป็นกรณี ๆ ไปข้อสันนิษฐานของฉันคือมันควรจะมีผลกระทบน้อยที่สุดต่อประสิทธิภาพที่ลดลงเมื่อเทียบกับวิธีแก้ปัญหาอื่น ๆ
นี่คือเวอร์ชันตัวพิมพ์ใหญ่ - เล็กที่จัดการค่า Null ด้วยเคสทดสอบส่วนใหญ่ที่เป็นไปได้:
SELECT
CASE
WHEN Date1 > coalesce(Date2,'0001-01-01') AND Date1 > coalesce(Date3,'0001-01-01') THEN Date1
WHEN Date2 > coalesce(Date3,'0001-01-01') THEN Date2
ELSE Date3
END AS MostRecentDate
, *
from
(values
( 1, cast('2001-01-01' as Date), cast('2002-01-01' as Date), cast('2003-01-01' as Date))
,( 2, cast('2001-01-01' as Date), cast('2003-01-01' as Date), cast('2002-01-01' as Date))
,( 3, cast('2002-01-01' as Date), cast('2001-01-01' as Date), cast('2003-01-01' as Date))
,( 4, cast('2002-01-01' as Date), cast('2003-01-01' as Date), cast('2001-01-01' as Date))
,( 5, cast('2003-01-01' as Date), cast('2001-01-01' as Date), cast('2002-01-01' as Date))
,( 6, cast('2003-01-01' as Date), cast('2002-01-01' as Date), cast('2001-01-01' as Date))
,( 11, cast(NULL as Date), cast('2002-01-01' as Date), cast('2003-01-01' as Date))
,( 12, cast(NULL as Date), cast('2003-01-01' as Date), cast('2002-01-01' as Date))
,( 13, cast('2003-01-01' as Date), cast(NULL as Date), cast('2002-01-01' as Date))
,( 14, cast('2002-01-01' as Date), cast(NULL as Date), cast('2003-01-01' as Date))
,( 15, cast('2003-01-01' as Date), cast('2002-01-01' as Date), cast(NULL as Date))
,( 16, cast('2002-01-01' as Date), cast('2003-01-01' as Date), cast(NULL as Date))
,( 21, cast('2003-01-01' as Date), cast(NULL as Date), cast(NULL as Date))
,( 22, cast(NULL as Date), cast('2003-01-01' as Date), cast(NULL as Date))
,( 23, cast(NULL as Date), cast(NULL as Date), cast('2003-01-01' as Date))
,( 31, cast(NULL as Date), cast(NULL as Date), cast(NULL as Date))
) as demoValues(id, Date1,Date2,Date3)
order by id
;
และผลลัพธ์คือ:
MostRecent id Date1 Date2 Date3
2003-01-01 1 2001-01-01 2002-01-01 2003-01-01
2003-01-01 2 2001-01-01 2003-01-01 2002-01-01
2003-01-01 3 2002-01-01 2001-01-01 2002-01-01
2003-01-01 4 2002-01-01 2003-01-01 2001-01-01
2003-01-01 5 2003-01-01 2001-01-01 2002-01-01
2003-01-01 6 2003-01-01 2002-01-01 2001-01-01
2003-01-01 11 NULL 2002-01-01 2003-01-01
2003-01-01 12 NULL 2003-01-01 2002-01-01
2003-01-01 13 2003-01-01 NULL 2002-01-01
2003-01-01 14 2002-01-01 NULL 2003-01-01
2003-01-01 15 2003-01-01 2002-01-01 NULL
2003-01-01 16 2002-01-01 2003-01-01 NULL
2003-01-01 21 2003-01-01 NULL NULL
2003-01-01 22 NULL 2003-01-01 NULL
2003-01-01 23 NULL NULL 2003-01-01
NULL 31 NULL NULL NULL
คุณสามารถสร้างฟังก์ชั่นที่คุณผ่านวันที่แล้วเพิ่มฟังก์ชั่นไปยังคำสั่ง select เช่นด้านล่าง เลือกตัวเลข, dbo.fxMost_Recent_Date (วันที่ 1, วันที่ 2, วันที่ 3), ราคา
create FUNCTION fxMost_Recent_Date
(@ Date1 smalldatetime, @ Date2 smalldatetime, @ Date3 smalldatetime) กลับมาอีกครั้ง smalldatetime เป็นการเริ่มต้นการประกาศ @Ressult smalldatetime
declare @MostRecent smalldatetime
set @MostRecent='1/1/1900'
if @Date1>@MostRecent begin set @MostRecent=@Date1 end
if @Date2>@MostRecent begin set @MostRecent=@Date2 end
if @Date3>@MostRecent begin set @MostRecent=@Date3 end
RETURN @MostRecent
END
อิงตามโซลูชันของScottPletcherจากhttp://www.experts-exchange.com/Microsoft/Development/MS-SQL-Server/Q_24204894.html ฉันได้สร้างชุดฟังก์ชัน (เช่น GetMaxOfDates3, GetMaxOfDates13) เพื่อหา max สูงถึง 13 ค่าวันที่โดยใช้ UNION ALL ดูฟังก์ชัน T-SQL เพื่อรับค่าสูงสุดจากแถวเดียวกัน อย่างไรก็ตามฉันไม่ได้พิจารณาโซลูชัน UNPIVOT ในขณะที่เขียนฟังก์ชันเหล่านี้
อีกวิธีในการใช้CASE เมื่อ
SELECT CASE true
WHEN max(row1) >= max(row2) THEN CASE true WHEN max(row1) >= max(row3) THEN max(row1) ELSE max(row3) end ELSE
CASE true WHEN max(row2) >= max(row3) THEN max(row2) ELSE max(row3) END END
FROM yourTable
ตารางด้านบนเป็นตารางเงินเดือนพนักงานที่มีเงินเดือน 1, เงินเดือน 2, เงินเดือน 3, เงินเดือน 4 เป็นคอลัมน์แบบสอบถามด้านล่างจะส่งคืนค่าสูงสุดจากสี่คอลัมน์
select
(select Max(salval) from( values (max(salary1)),(max(salary2)),(max(salary3)),(max(Salary4)))alias(salval)) as largest_val
from EmployeeSalary
การเรียกใช้คิวรีด้านบนจะให้ผลลัพธ์เป็น large_val (1,0001)
ตรรกะของแบบสอบถามด้านบนมีดังนี้:
select Max(salvalue) from(values (10001),(5098),(6070),(7500))alias(salvalue)
เอาต์พุตจะเป็น 1,0001
นี่เป็นทางออกที่ดี:
CREATE function [dbo].[inLineMax] (@v1 float,@v2 float,@v3 float,@v4 float)
returns float
as
begin
declare @val float
set @val = 0
declare @TableVal table
(value float )
insert into @TableVal select @v1
insert into @TableVal select @v2
insert into @TableVal select @v3
insert into @TableVal select @v4
select @val= max(value) from @TableVal
return @val
end
ฉันไม่ทราบว่ามันอยู่ใน SQL ฯลฯ ... ใน M $ ACCESS ช่วยมีฟังก์ชั่นที่เรียกMAXA(Value1;Value2;...)
ว่าควรจะทำเช่นนั้น
หวังว่าจะช่วยใครบางคน
PD: ค่าสามารถเป็นคอลัมน์หรือค่าที่คำนวณได้ ฯลฯ
MAXA
เป็นฟังก์ชัน Excelไม่ใช่การเข้าถึง
WHEN Date1 > Date2 AND Date1 > Date3 THEN Date1; WHEN Date2 > Date3 THEN Date3; ELSE Date3
หรือไม่