2016-04-19 15 views
9

sql fiddle demo hereLàm thế nào tôi có thể nhóm các kết quả theo ngày trong truy vấn này với SQL Server?

Tôi có cấu trúc này bảng cho bảng Diary:

CREATE TABLE Diary 
(
    [IdDiary] bigint, 
    [UserId] int, 
    [IdDay] numeric(18,0), 
    [IsAnExtraHour] bit 
); 

INSERT INTO Diary ([IdDiary], [UserId], [IdDay], [IsAnExtraHour]) 
values 
(51, 1409, 1, 0), 
(52, 1409, 1, 1), 
(53, 1409, 3, 0), 
(54, 1409, 5, 0), 
(55, 1409, 5, 1), 
(56, 1408, 2, 0); 

Và cấu trúc này cho bảng DiaryTimetable:

CREATE TABLE DiaryTimetable 
(
    [IdDiary] bigint, 
    [Hour] varchar(50) 
); 

    INSERT INTO DiaryTimetable ([IdDiary], [Hour]) 
VALUES 
    (51, '09:00'), 
    (51, '09:30'), 
    (51, '10:00'), 
    (51, '10:30'), 
    (51, '11:00'), 
    (52, '15:00'), 
    (52, '15:30'), 
    (52, '16:00'), 
    (52, '16:30'), 
    (52, '17:00'), 
    (53, '11:00'), 
    (53, '11:30'), 
    (53, '12:00'), 
    (53, '12:30'), 
    (53, '13:00'), 
    (54, '10:00'), 
    (54, '10:30'), 
    (54, '11:00'), 
    (54, '11:30'), 
    (54, '12:00'), 
    (55, '16:00'), 
    (55, '16:30'), 
    (55, '17:00'), 
    (55, '17:30'), 
    (55, '18:00'), 
    (56, '15:00'), 
    (56, '15:30'), 
    (56, '16:00'), 
    (56, '16:30'), 
    (56, '17:00'); 

tôi đã sử dụng truy vấn này để có được những giờ max và giờ phút cho userid 1409, để có được mỗi ngày thời gian đó nhập và thời gian mà rời khỏi công việc. Ngày idday tương ứng với số ngày trong tuần. Ví dụ 1 là thứ hai, thứ ba là 2 vv ...

SELECT d.IdDiary, d.IdDay, MIN(Hour) as 'Start Time', MAX(Hour) as 'End Time', IsAnExtraHour 
FROM Diary AS d 
LEFT JOIN DiaryTimetable AS dt ON d.IdDiary = dt.IdDiary 
where userid = 1409 
GROUP BY d.IdDiary, d.IdDay, IsAnExtraHour 

Truy vấn này cho kết quả này:

enter image description here

Tôi muốn để có được kết quả này:

Day  Start Time End Time Start Extra Time End Extra Time 
    -----  ---------- -------- ---------------  --------------- 
    Monday  09:00   11:00  15:00    17:00 
    Wednessday 11:00   13:00   
    Friday  10:00   12:00  16:00    18:00 

tôi có một cột (IsAnExtraHour) cột này cho biết nếu hàng này có thêm giờ trong một ngày, ví dụ như một công việc bắt đầu sử dụng lao động vào thứ hai tại 09:00 đến 11:00 và sau đó hoạt động trở lại vào buổi chiều lúc 15: 00-17: 00, vì vậy tôi muốn biết làm thế nào tôi có thể nhóm giờ này trong cùng một hàng, tôi hy vọng tôi đã có thể thể hiện rõ ràng, tôi chấp nhận lời đề nghị cảm ơn.

+10

Đó là cách người ta nên đặt câu hỏi SQL. Tất cả đều làm như Esraa_92! – Quassnoi

+2

Cảm ơn bạn đã bình luận của bạn ;-D –

+0

Không sử dụng dấu nháy đơn cho bí danh cột. Để tránh nhầm lẫn và khó tìm lỗi, bạn nên sử dụng dấu nháy đơn chỉ cho chuỗi và ngày/thời gian hằng số. –

Trả lời

9
SELECT d.IdDay, 
     MIN(CASE WHEN isAnExtraHour = 0 THEN hour END) as 'Start Time', 
     MAX(CASE WHEN isAnExtraHour = 0 THEN hour END) as 'End Time', 
     MIN(CASE WHEN isAnExtraHour = 1 THEN hour END) as 'Start Extra Time', 
     MAX(CASE WHEN isAnExtraHour = 1 THEN hour END) as 'End Extra Time' 
FROM Diary AS d 
LEFT JOIN 
     DiaryTimetable AS dt 
ON  dt.IdDiary = d.IdDiary 
WHERE userid = 1409 
GROUP BY 
     d.IdDay 
+0

Cảm ơn câu trả lời của bạn rất dễ hiểu: -D –

1

Cách tôi tiếp cận điều này sẽ là tính riêng giờ tiêu chuẩn và giờ phụ của bạn, một cái gì đó như thế này;

SELECT d.IdDay 
    ,MIN(dt.StartTime) AS 'Start Time' 
    ,MAX(dt.EndTime) AS 'End Time' 
    ,MIN(ex.StartTime) AS 'Start Extra Time' 
    ,MAX(ex.EndTime) AS 'End Extra Time' 
FROM Diary AS d 
LEFT JOIN (
    SELECT IdDiary 
     ,MIN(Hour) AS StartTime 
     ,MAX(Hour) AS EndTime 
    FROM DiaryTimetable 
    GROUP BY IdDiary 
    ) AS dt ON d.IdDiary = dt.IdDiary 
    AND d.IsAnExtraHour = 0 
LEFT JOIN (
    SELECT IdDiary 
     ,MIN(Hour) AS StartTime 
     ,MAX(Hour) AS EndTime 
    FROM DiaryTimetable 
    GROUP BY IdDiary 
    ) AS ex ON d.IdDiary = ex.IdDiary 
    AND d.IsAnExtraHour = 1 
WHERE userid = 1409 
GROUP BY d.IdDay 
+0

Tất nhiên, bạn có thể làm một tuyên bố trường hợp trên IdDay hoặc liên kết nó với một bảng ngày nếu bạn có một để trả lại ngày làm văn bản (ví dụ như thứ hai thay vì 1) –

1

Trước tiên, bạn có thể nhận được thêm giờ và để họ tham gia thêm giờ bởi UserId và IdDay. Như thế này:

SELECT 
    CASE BaseHours.IdDay 
     WHEN 1 THEN 'Monday' 
     WHEN 2 THEN 'Tuesday' 
     WHEN 3 THEN 'Wednesday' 
     WHEN 4 THEN 'Thursday' 
     WHEN 5 THEN 'Friday' 
     WHEN 6 THEN 'Saturday' 
     WHEN 7 THEN 'Sunday' 
    END AS [WeekDay], 
    MIN(BaseTimeTable.Hour) as 'Start Time', 
    MAX(BaseTimeTable.Hour) as 'End Time', 
    MIN(ExtraTimeTable.Hour) as 'Start Extra Time', 
    MAX(ExtraTimeTable.Hour) as 'End Extra Time' 
FROM Diary AS BaseHours 
LEFT JOIN Diary ExtraHours 
    ON ExtraHours.UserId = BaseHours.UserId 
     AND ExtraHours.IdDay = BaseHours.IdDay AND ExtraHours.IsAnExtraHour = 1 
JOIN DiaryTimetable AS BaseTimeTable 
    ON BaseHours.IdDiary = BaseTimeTable.IdDiary 
LEFT JOIN DiaryTimetable AS ExtraTimeTable 
    ON ExtraHours.IdDiary = ExtraTimeTable.IdDiary 
WHERE BaseHours.Userid = 1409 AND BaseHours.IsAnExtraHour = 0 
GROUP BY BaseHours.IdDay 
5

tôi sử dụng mã từ @Quassnoi và tôi thêm này:

SELECT DATENAME(weekday, d.idday-1) as 'Day' , 
     MIN(CASE WHEN isAnExtraHour = 0 THEN hour END) AS 'Start Time', 
     MAX(CASE WHEN isAnExtraHour = 0 THEN hour END) AS 'End Time', 
     MIN(CASE WHEN isAnExtraHour = 1 THEN hour END) AS 'Start Extra Time', 
     MAX(CASE WHEN isAnExtraHour = 1 THEN hour END) AS 'End Extra Time' 
FROM Diary AS d 
LEFT JOIN DiaryTimetable AS dt ON dt.IdDiary = d.IdDiary 
WHERE userid = 1409 
GROUP BY d.IdDay 

Tôi hy vọng điều này giúp đỡ một ai đó, cảm ơn tất cả những câu trả lời của mình.

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