今天下午我有一点'大脑褪色',所以如果有人可以帮助这个mssql查询,那就太棒了。
我有一个名为'season'的表,有三列(有更多但与示例无关):seasonId,date,tariffId
SeasonId是一个独特的关键。 日期只能有一个的关税,但是关税可以有很多不同的日期。
例如:
seasonId | date | tariffId
----------------------------------
1 | 1 jan 2009 | 1
2 | 2 jan 2009 | 1
3 | 3 jan 2009 | 2
4 | 4 jan 2009 | 3
5 | 5 jan 2009 | 3
我希望查询返回特定关税的日期序列/范围
例如,使用上面的数据,它将返回以下内容:
FromDate | ToDate | TariffId
-----------------------------------
1 | Jan 2009 2 | Jan 2009 1
3 | Jan 2009 3 | Jan 2009 2
4 | Jan 2009 5 | Jan 2009 3
这可能吗?
修改 谢谢你到目前为止的所有答案!我总是惊讶你得到了多少回应!
但是,我的示例数据可能不够复杂,因为关税可以有1个或更多日期范围
seasonId | date | tariffId
----------------------------------
1 | 1 jan 2009 | 1
2 | 2 jan 2009 | 1
3 | 3 jan 2009 | 2
4 | 4 jan 2009 | 3
5 | 5 jan 2009 | 3
6 | 6 jan 2009 | 1
7 | 7 jan 2009 | 1
8 | 8 jan 2009 | 3
会给:
FromDate | ToDate | TariffId
------------------------------------
1 Jan 2009 | 2 Jan 2009 | 1
3 Jan 2009 | 3 Jan 2009 | 2
4 Jan 2009 | 5 Jan 2009 | 3
6 Jan 2009 | 7 Jan 2009 | 1
8 Jan 2009 | 8 Jan 2009 | 3
想法?
感谢大家对此的帮助!这个网站太棒了!
答案 0 :(得分:3)
首先是一些测试数据:
create table seasons (seasonId int primary key
, "date" datetime not null unique
, tariffId int not null)
insert into seasons values (1, '2009-01-01', 1)
insert into seasons values (2, '2009-01-02', 1)
insert into seasons values (3, '2009-01-03', 2)
insert into seasons values (4, '2009-01-04', 3)
insert into seasons values (5, '2009-01-05', 3)
insert into seasons values (6, '2009-01-06', 1)
insert into seasons values (7, '2009-01-07', 1)
insert into seasons values (8, '2009-01-08', 3)
-- add a tarrif with a datespan larger than 2
insert into seasons values (9, '2009-01-09', 4)
insert into seasons values (10, '2009-01-10', 4)
insert into seasons values (11, '2009-01-11', 4)
在Dave Barker的回答基础上,在内联视图中添加row_number(),以便我们知道哪个是第一个最小值,这是第二个,等等。 (实际上由于日期不能有一个以上的关税,我们不需要按关税分配。)
SELECT MinValues.Seasonid, MinValues.Date, MaxValues.Date, MaxValues.tariffid
FROM (
SELECT *, row_number() over (partition by tariffId order by "date") as RN
FROM [dbo].[Seasons] tbl1
WHERE NOT EXISTS (SELECT *
FROM [dbo].[Seasons] tbl2
WHERE tbl1.seasonid - tbl2.seasonid = 1
AND tbl1.tariffId = tbl2.tariffId)) as minValues
JOIN (
SELECT *, row_number() over (partition by tariffId order by "date") as RN
FROM [dbo].[Seasons] tbl1
WHERE NOT EXISTS (SELECT *
FROM [dbo].[Seasons] tbl2
WHERE tbl2.seasonid - tbl1.seasonid = 1
AND tbl1.tariffId = tbl2.tariffId)) as maxValues
ON MinValues.TariffId = MaxValues.tariffId
and MinValues.RN = MaxValues.RN
order by MinValues.Date
结果:
1 2009-01-01 00:00:00.000 2009-01-02 00:00:00.000 1
3 2009-01-03 00:00:00.000 2009-01-03 00:00:00.000 2
4 2009-01-04 00:00:00.000 2009-01-05 00:00:00.000 3
6 2009-01-06 00:00:00.000 2009-01-07 00:00:00.000 1
8 2009-01-08 00:00:00.000 2009-01-08 00:00:00.000 3
9 2009-01-09 00:00:00.000 2009-01-11 00:00:00.000 4
答案 1 :(得分:2)
SELECT min(date) as FromDate, MAX(date) as ToDate, tarifid
FROM seasons
GROUP BY tarifID
应该这样做。
答案 2 :(得分:2)
SELECT min(date) as FromDate,MAX(date) as ToDate, tariffid FROM(
select s.*,ISNULL(
(SELECT MAX(seasonID) FROM seasons s1 WHERE s.tariffid <> s1.tariffid AND s1.seasonID < s.seasonID),0) as ranks from seasons s)r
GROUP BY tariffID,ranks
答案 3 :(得分:0)
也许这个?
select min(fromdate) as FromDate, max(todate) as ToDate, tarifid
from (
select min(date) as fromdate, null as todate, tarifid
from seasons
group by tarifid
union
select null, max(date), tarifid
from seasons
group by tarifid
) q
group by tarifid
答案 4 :(得分:0)
看起来您发现了tariffId的连续出现,然后在该连续出现中找到Date的最小值和最大值。以下适用于您的样本数据但我怀疑最终加入需要一些调整,因为它感觉很臭。
SELECT MinValues.Seasonid, MinValues.Date, MaxValues.Date, MaxValues.tariffid
FROM (
SELECT *
FROM [dbo].[Seasons] tbl1
WHERE NOT EXISTS (SELECT *
FROM [dbo].[Seasons] tbl2
WHERE tbl1.seasonid - tbl2.seasonid = 1
AND tbl1.tariffId = tbl2.tariffId)) as minValues
JOIN (
SELECT *
FROM [dbo].[Seasons] tbl1
WHERE NOT EXISTS (SELECT *
FROM [dbo].[Seasons] tbl2
WHERE tbl2.seasonid - tbl1.seasonid = 1
AND tbl1.tariffId = tbl2.tariffId)) as maxValues
ON MinValues.TariffId = MaxValues.tariffId
AND (MinValues.SeasonId = MaxValues.Seasonid or MinValues.SeasonId +1 = MaxValues.Seasonid)