我手上有一张凌乱的桌子,有两个字段,一个日期字段和一个时间字段,都是字符串。我需要做的是从那些字段中获取最小日期,或者如果没有附加日期/时间则只记录记录本身。以下是一些示例数据:
ID First Last Date Time
1 Joe Smith 2013-09-06 04:00
1 Joe Smith 2013-09-06 02:00
2 Jack Jones
3 John Jack 2013-09-05 06:00
3 John Jack 2013-09-15 15:00
我希望从查询中获得以下内容:
ID First Last Date Time
1 Joe Smith 2013-09-06 02:00
2 Jack Jones
3 John Jack 2013-09-05 06:00
ID 1和3的最小日期/时间,然后是ID 2,因为他没有日期/时间。我提出了以下查询,它完全按照我的要求给出了ID 1和3:
SELECT *
FROM test as t
where
cast(t.date + ' ' + t.time as Datetime ) = (select top 1 cast(p.date + ' ' + p.time as Datetime ) as dtime from test as p where t.ID = p.ID order by dtime)
但它根本不会返回第2行。我想有一个更好的方法来做这件事。有什么想法吗?
答案 0 :(得分:2)
您可以使用row_number()
:
select ID, First, Last, Date, Time
from (select t.*,
row_number() over (partition by id order by date, time) as seqnum
from test t
) t
where seqnum = 1;
虽然不建议将日期和时间存储为字符串,但至少要做到正确。这些值使用ISO标准格式(或足够接近),因此字母排序与日期/时间排序相同。
答案 1 :(得分:1)
假设[Date]
和[Time]
是我认为的类型,而不是字符串:
SELECT ID,[First],[Last],[Date],[Time] FROM
(
SELECT ID,[First],[Last],[Date],[Time],rn = ROW_NUMBER()
OVER (PARTITION BY ID ORDER BY [Date], [Time])
FROM dbo.test
) AS t WHERE rn = 1;
示例:
DECLARE @x TABLE
(
ID INT,
[First] VARCHAR(32),
[Last] VARCHAR(32),
[Date] DATE,
[Time] TIME(0)
);
INSERT @x VALUES
(1,'Joe ','Smith','2013-09-06','04:00'),
(1,'Joe ','Smith','2013-09-06','02:00'),
(2,'Jack','Jones',NULL, NULL ),
(3,'John','Jack ','2013-09-05','06:00'),
(3,'John','Jack ','2013-09-15','15:00');
SELECT ID,[First],[Last],[Date],[Time] FROM
(
SELECT ID, [First],[Last],[Date],[Time],rn = ROW_NUMBER()
OVER (PARTITION BY ID ORDER BY [Date], [Time])
FROM @x
) AS x WHERE rn = 1;
结果:
ID First Last Date Time
-- ----- ----- ---------- --------
1 Joe Smith 2013-09-06 02:00:00
2 Jack Jones NULL NULL
3 John Jack 2013-09-05 06:00:00
答案 2 :(得分:0)
尝试:
SELECT
*
FROM
test as t
WHERE
CAST(t.date + ' ' + t.time as Datetime) =
(
select top 1 cast(p.date + ' ' + p.time as Datetime ) as dtime
from test as p
where t.ID = p.ID
order by dtime
)
OR (t.date='' AND t.time='')