我需要一点帮助......所以,让我向你介绍我的问题。
我有以下SQL Server表:
| RankCode | SeaPortInd | WatchKeepingInd | EffectiveDate | VesselCode | FromDate | ToDate | LastDate | LastUser |
+----------+------------+-----------------+-------------------------+------------+-------------------------+-------------------------+-------------------------+----------+
| C/E | 0 | 0 | 1900-01-01 00:00:00.000 | 031 | 1900-01-01 05:00:00.000 | 1900-01-01 07:00:00.000 | 2016-08-11 12:40:00.000 | d.baltas |
| C/E | 0 | 0 | 2016-06-02 00:00:00.000 | 031 | 1900-01-01 00:00:00.000 | 1900-01-01 00:00:00.000 | 1900-01-01 00:00:00.000 | d.baltas |
| C/E | 0 | 1 | 2016-06-01 00:00:00.000 | 031 | 1900-01-01 01:00:00.000 | 1900-01-01 02:00:00.000 | 2016-08-11 17:58:00.000 | d.baltas |
| C/E | 0 | 1 | 2016-06-02 00:00:00.000 | 031 | 1900-01-01 01:00:00.000 | 1900-01-01 02:00:00.000 | 2016-08-10 17:58:00.000 | d.baltas |
| C/E | 1 | 1 | 2016-06-01 00:00:00.000 | 031 | 1900-01-01 03:00:00.000 | 1900-01-01 04:00:00.000 | 2016-08-10 17:58:00.000 | d.baltas |
| MSTR | 0 | 0 | 2016-06-02 00:00:00.000 | 031 | 1900-01-01 16:00:00.000 | 1900-01-01 22:00:00.000 | 2016-08-10 17:58:00.000 | d.baltas |
| MSTR | 0 | 1 | 2016-06-01 00:00:00.000 | 031 | 1900-01-01 08:00:00.000 | 1900-01-01 12:00:00.000 | 2016-08-10 17:58:00.000 | d.baltas |
| MSTR | 1 | 0 | 2016-06-03 00:00:00.000 | 031 | 1900-01-01 08:00:00.000 | 1900-01-01 14:00:00.000 | 2016-08-11 15:00:00.000 | d.baltas |
+----------+------------+-----------------+-------------------------+------------+-------------------------+-------------------------+-------------------------+----------+
我想获取类似于此表的输出:
表格的更多解释:
海上预定的每日工作时间表示SeaPortInd = 1
港口的预定每日工作时间表示SeaPortInd = 0
值守是指WatchkeepingInd = 1
NonWatchkeeping表示WatchkeepingInd = 0
我设法进入下表:
+----------+--------------------+
| RankCode | SeaNonWatchkeeping |
| C/E | 00:00 - 00:00 |
| | 05:00 - 07:00 |
| MSTR | 16:00 - 22:00 |
+----------+--------------------+
查询:
SELECT CASE
WHEN row_number() OVER (
PARTITION BY RankCode ORDER BY FromDate asc
) = 1
THEN RankCode
ELSE ''
END AS RankCode
,substring(convert(VARCHAR(255), FromDate, 120), 11, 6) + ' -' + substring(convert(VARCHAR(255), ToDate, 120), 11, 6) AS SeaNonWatchkeeping
FROM WorkingHoursSchedule WHERE SeaPortInd = 0 AND watchkeepingind = 0
你能帮我解决一下SeaportInd = 0和Watchkeeping = 1等问题吗?
我正在使用SQL Server 2008,但查询也将在一些以前最低版本的SQL Server 2005上运行
提前致谢!
答案 0 :(得分:1)
这个应该有效:
WITH WorkingHoursSchedule AS
(
SELECT * FROM (VALUES
('C/E ', 0, 0, '1900-01-01 00:00:00.000', '031', '1900-01-01 05:00:00.000', '1900-01-01 07:00:00.000', '2016-08-11 12:40:00.000', 'd.baltas'),
('C/E ', 0, 0, '2016-06-02 00:00:00.000', '031', '1900-01-01 00:00:00.000', '1900-01-01 00:00:00.000', '1900-01-01 00:00:00.000', 'd.baltas'),
('C/E ', 0, 1, '2016-06-01 00:00:00.000', '031', '1900-01-01 01:00:00.000', '1900-01-01 02:00:00.000', '2016-08-11 17:58:00.000', 'd.baltas'),
('C/E ', 0, 1, '2016-06-02 00:00:00.000', '031', '1900-01-01 01:00:00.000', '1900-01-01 02:00:00.000', '2016-08-10 17:58:00.000', 'd.baltas'),
('C/E ', 1, 1, '2016-06-01 00:00:00.000', '031', '1900-01-01 03:00:00.000', '1900-01-01 04:00:00.000', '2016-08-10 17:58:00.000', 'd.baltas'),
('MSTR', 0, 0, '2016-06-02 00:00:00.000', '031', '1900-01-01 16:00:00.000', '1900-01-01 22:00:00.000', '2016-08-10 17:58:00.000', 'd.baltas'),
('MSTR', 0, 1, '2016-06-01 00:00:00.000', '031', '1900-01-01 08:00:00.000', '1900-01-01 12:00:00.000', '2016-08-10 17:58:00.000', 'd.baltas'),
('MSTR', 1, 0, '2016-06-03 00:00:00.000', '031', '1900-01-01 08:00:00.000', '1900-01-01 14:00:00.000', '2016-08-11 15:00:00.000', 'd.baltas')
)T(RankCode, SeaPortInd, WatchKeepingInd, EffectiveDate, VesselCode, FromDate, ToDate, LastDate, LastUser)
), Src AS
(
SELECT ROW_NUMBER() OVER (PARTITION BY RankCode ORDER BY RankCode, SeaPortInd, WatchKeepingInd) RN, RankCode
FROM WorkingHoursSchedule
), SeaWatchKeeping AS
(
SELECT ROW_NUMBER() OVER (PARTITION BY RankCode ORDER BY FromDate) RN, RankCode,
SUBSTRING(CONVERT(VARCHAR(255), FromDate, 120), 12, 5) + ' - ' + SUBSTRING(CONVERT(VARCHAR(255), ToDate, 120), 12, 5) SeaWatchKeeping
FROM WorkingHoursSchedule
WHERE SeaPortInd = 0 AND WatchKeepingInd = 1
), SeaNonWatchKeeping AS
(
SELECT ROW_NUMBER() OVER (PARTITION BY RankCode ORDER BY FromDate) RN, RankCode,
SUBSTRING(CONVERT(VARCHAR(255), FromDate, 120), 12, 5) + ' - ' + SUBSTRING(CONVERT(VARCHAR(255), ToDate, 120), 12, 5) SeaNonWatchKeeping
FROM WorkingHoursSchedule
WHERE SeaPortInd = 0 AND WatchKeepingInd = 0
), LandWatchKeeping AS
(
SELECT ROW_NUMBER() OVER (PARTITION BY RankCode ORDER BY FromDate) RN, RankCode,
SUBSTRING(CONVERT(VARCHAR(255), FromDate, 120), 12, 5) + ' - ' + SUBSTRING(CONVERT(VARCHAR(255), ToDate, 120), 12, 5) LandWatchKeeping
FROM WorkingHoursSchedule
WHERE SeaPortInd = 1 AND WatchKeepingInd = 1
), LandNonWatchKeeping AS
(
SELECT ROW_NUMBER() OVER (PARTITION BY RankCode ORDER BY FromDate) RN, RankCode,
SUBSTRING(CONVERT(VARCHAR(255), FromDate, 120), 12, 5) + ' - ' + SUBSTRING(CONVERT(VARCHAR(255), ToDate, 120), 12, 5) LandNonWatchKeeping
FROM WorkingHoursSchedule
WHERE SeaPortInd = 1 AND WatchKeepingInd = 0
)
SELECT CASE WHEN S.RN=1 THEN S.RankCode ELSE NULL END RankCode, SeaWatchKeeping, SeaNonWatchKeeping, LandWatchKeeping, LandNonWatchKeeping
FROM Src S
LEFT JOIN SeaNonWatchKeeping SN ON S.RN=SN.RN AND S.RankCode=SN.RankCode
LEFT JOIN SeaWatchKeeping SW ON S.RN=SW.RN AND S.RankCode=SW.RankCode
LEFT JOIN LandNonWatchKeeping LN ON S.RN=LN.RN AND S.RankCode=LN.RankCode
LEFT JOIN LandWatchKeeping LW ON S.RN=LW.RN AND S.RankCode=LW.RankCode
WHERE SeaWatchKeeping IS NOT NULL OR SeaNonWatchKeeping IS NOT NULL OR LandWatchKeeping IS NOT NULL OR LandNonWatchKeeping IS NOT NULL
行根据RankCode
占用的空间折叠,并按FromDate
排序:
RankCode SeaWatchKeeping SeaNonWatchKeeping LandWatchKeeping LandNonWatchKeeping
-------- --------------- ------------------ ---------------- -------------------
C/E 01:00 - 02:00 00:00 - 00:00 03:00 - 04:00 NULL
NULL 01:00 - 02:00 05:00 - 07:00 NULL NULL
MSTR 08:00 - 12:00 16:00 - 22:00 NULL 08:00 - 14:00
答案 1 :(得分:0)
以下SQL使用CASE表达式根据您的要求进行评估。
SELECT [RankCode]
, CASE
WHEN [SeaPortInd] = 1 AND [WatchKeepingInd] = 1 THEN substring(convert(VARCHAR(255), [FromDate], 120), 11, 6) + ' -' + substring(convert(VARCHAR(255), [ToDate], 120), 11, 6)
END as 'At Sea: Watchkeeping (from...to)'
, CASE
WHEN [SeaPortInd] = 1 AND [WatchKeepingInd] = 0 THEN substring(convert(VARCHAR(255), [FromDate], 120), 11, 6) + ' -' + substring(convert(VARCHAR(255), [ToDate], 120), 11, 6)
END as 'At Sea: Non-Watchkeeping duties (from...to)'
, CASE
WHEN [SeaPortInd] = 0 AND [WatchKeepingInd] = 1 THEN substring(convert(VARCHAR(255), [FromDate], 120), 11, 6) + ' -' + substring(convert(VARCHAR(255), [ToDate], 120), 11, 6)
END as 'In Port: Watchkeeping (from...to)'
, CASE
WHEN [SeaPortInd] = 0 AND [WatchKeepingInd] = 0 THEN substring(convert(VARCHAR(255), [FromDate], 120), 11, 6) + ' -' + substring(convert(VARCHAR(255), [ToDate], 120), 11, 6)
END as 'In Port: Non-Watchkeeping duties (from...to)'
FROM [dbo].[WorkingHoursSchedule]
答案 2 :(得分:0)
我认为每艘船都有自己的时间表,允许一次检索多艘船只。此解决方案使用计数表来创建插槽。
--original data
declare @WorkingHoursSchedule table (
Ident int identity(1,1),
RankCode varchar(5),
SeaPortInd bit,
WatchKeepingInd bit,
EffectiveDate datetime,
VesselCode varchar(5),
FromDate datetime,
ToDate datetime,
LastDate datetime,
LastUser varchar(128));
insert @WorkingHoursSchedule values
('C/E',0,0,'1900-01-01 00:00:00.000','031','1900-01-01 05:00:00.000','1900-01-01 07:00:00.000','2016-08-11 12:40:00.000','d.baltas'),
('C/E',0,0,'2016-06-02 00:00:00.000','031','1900-01-01 00:00:00.000','1900-01-01 00:00:00.000','1900-01-01 00:00:00.000','d.baltas'),
('C/E',0,1,'2016-06-01 00:00:00.000','031','1900-01-01 01:00:00.000','1900-01-01 02:00:00.000','2016-08-11 17:58:00.000','d.baltas'),
('C/E',0,1,'2016-06-02 00:00:00.000','031','1900-01-01 01:00:00.000','1900-01-01 02:00:00.000','2016-08-10 17:58:00.000','d.baltas'),
('C/E',1,1,'2016-06-01 00:00:00.000','031','1900-01-01 03:00:00.000','1900-01-01 04:00:00.000','2016-08-10 17:58:00.000','d.baltas'),
('MSTR',0,0,'2016-06-02 00:00:00.000','031','1900-01-01 16:00:00.000','1900-01-01 22:00:00.000','2016-08-10 17:58:00.000','d.baltas'),
('MSTR',0,1,'2016-06-01 00:00:00.000','031','1900-01-01 08:00:00.000','1900-01-01 12:00:00.000','2016-08-10 17:58:00.000','d.baltas'),
('MSTR',1,0,'2016-06-03 00:00:00.000','031','1900-01-01 08:00:00.000','1900-01-01 14:00:00.000','2016-08-11 15:00:00.000','d.baltas');
--create and populate tally table if you don't already a permanent one - arbitrary 1000 rows for demo...you should figure out if that is enough
declare @Tally table (N int PRIMARY KEY);
insert @Tally
select top (1000) row_number() over (order by o1.object_id) from sys.columns o1, sys.columns o2 order by 1;
--select * from @Tally order by N;
with ranked_slots_cte as ( --ranked slots by vessel/rank for each combination of indicator
select *, row_number() over (partition by VesselCode, RankCode, SeaPortInd, WatchKeepingInd order by FromDate) time_slot
from @WorkingHoursSchedule
--where EffectiveDate <= getdate() and (LastDate is null or LastDate > getdate()) --it looks like this might be a good place to check these values
--where VesselCode = '031' --I assumed getting schedules for all vessels with grouping, but you could filter here instead.
)
select max_slots.VesselCode, max_slots.RankCode, slots.N TimeSlot
, substring(convert(VARCHAR(255), r1.FromDate, 120), 11, 6) + ' -' + substring(convert(VARCHAR(255), r1.ToDate, 120), 11, 6)
, substring(convert(VARCHAR(255), r2.FromDate, 120), 11, 6) + ' -' + substring(convert(VARCHAR(255), r2.ToDate, 120), 11, 6)
, substring(convert(VARCHAR(255), r3.FromDate, 120), 11, 6) + ' -' + substring(convert(VARCHAR(255), r3.ToDate, 120), 11, 6)
, substring(convert(VARCHAR(255), r4.FromDate, 120), 11, 6) + ' -' + substring(convert(VARCHAR(255), r4.ToDate, 120), 11, 6)
from (--total slots per vessel/rank
select VesselCode, RankCode, max(time_slot) max_slot
from ranked_slots_cte
group by VesselCode, RankCode
--order by VesselCode, RankCode
) max_slots
join @Tally slots --create the appropriate number of slots per vessel/rank
on slots.N <= max_slots.max_slot
--join each of the appropriate indicator combinations by ranked time slot
left join ranked_slots_cte r1 --At Sea/Watch
on r1.VesselCode = max_slots.VesselCode
and r1.RankCode = max_slots.RankCode
and r1.time_slot = slots.N
and r1.SeaPortInd = 1
and r1.WatchKeepingInd = 1
left join ranked_slots_cte r2 --At Sea/Not Watch
on r2.VesselCode = max_slots.VesselCode
and r2.RankCode = max_slots.RankCode
and r2.time_slot = slots.N
and r2.SeaPortInd = 1
and r2.WatchKeepingInd = 0
left join ranked_slots_cte r3 --In Port/Watch
on r3.VesselCode = max_slots.VesselCode
and r3.RankCode = max_slots.RankCode
and r3.time_slot = slots.N
and r3.SeaPortInd = 0
and r3.WatchKeepingInd = 1
left join ranked_slots_cte r4 --In Port/Not Watch
on r4.VesselCode = max_slots.VesselCode
and r4.RankCode = max_slots.RankCode
and r4.time_slot = slots.N
and r4.SeaPortInd = 0
and r4.WatchKeepingInd = 0
order by max_slots.VesselCode, max_slots.RankCode, slots.N;
输出如下:
031 C/E 1 03:00 - 04:00 NULL 01:00 - 02:00 00:00 - 00:00
031 C/E 2 NULL NULL 01:00 - 02:00 05:00 - 07:00
031 MSTR 1 NULL 08:00 - 14:00 08:00 - 12:00 16:00 - 22:00