Chọn COUNT ngày giữa hai ngày trừ cuối tuần


9

Tôi đang cố gắng để có được số ngày giữa hai ngày khác nhau, ngoại trừ cuối tuần.

Tôi không biết làm thế nào để đạt được kết quả này.


1
Vui lòng gửi cấu trúc bảng của bạn để tham khảo. Cuối tuần có nghĩa là SAT và SUN?
Abdul Manaf

Câu trả lời:


10

Giả sử rằng vào "cuối tuần", bạn có nghĩa là thứ bảychủ nhật , điều này có thể đơn giản hơn nữa:

SELECT count(*) AS count_days_no_weekend
FROM   generate_series(timestamp '2014-01-01'
                     , timestamp '2014-01-10'
                     , interval  '1 day') the_day
WHERE  extract('ISODOW' FROM the_day) < 6;
  • Bạn không cần một cấp độ phụ cho generate_series(). SRF (thiết lập các hàm trả về), còn được gọi là "các hàm bảng", có thể được sử dụng giống như các bảng trong FROMmệnh đề.

  • Đặc biệt lưu ý generate_series() bao gồm giới hạn trên trong đầu ra, miễn là khoảng thời gian đầy đủ (tham số thứ 3) phù hợp. Giới hạn trên chỉ được loại trừ nếu khoảng thời gian cuối cùng sẽ bị cắt ngắn, đây không phải là trường hợp có đầy đủ ngày.

  • Với mẫu ISODOWcho EXTRACT () , Chủ nhật được báo cáo là 7, theo tiêu chuẩn ISO. Cho phép một WHEREđiều kiện đơn giản hơn .

  • Thay vì gọi generate_series()với timestampđầu vào. Đây là lý do tại sao:

  • count(*)ngắn hơn một chút và nhanh hơn count(the_day), làm tương tự trong trường hợp này.

Để loại trừ giới hạn dưới và / hoặc giới hạn trên, hãy thêm / bớt 1 ngày tương ứng. Thông thường, bạn có thể bao gồm giới hạn dưới và loại trừ giới hạn trên:

SELECT count(*) AS count_days_no_weekend
FROM   generate_series(timestamp '2014-01-01'
                     , timestamp '2014-01-10' - interval '1 day'
                     , interval '1 day') the_day
WHERE  extract('ISODOW' FROM the_day) < 6;

3

Ví dụ này liệt kê tất cả các ngày trong khoảng thời gian 2013-12-15 và 2014-01 / 02 (bao gồm). Cột thứ hai cho ngày trong tuần (bằng số, từ 0 đến 6). Cột thứ ba đánh dấu xem ngày trong tuần có phải là Thứ Bảy / Chủ Nhật hay không (bạn sẽ phải điều chỉnh những gì bạn cho là cuối tuần) và là những gì có thể được sử dụng để đếm các ngày trong tuần.

select '2013-12-15'::date + i * interval '1 day',
       extract('dow' from '2013-12-15'::date + i * interval '1 day') as dow,
       case when extract('dow' from '2013-12-15'::date + i * interval '1 day') in (0, 6)
               then false
            else true end as is_weekday
from generate_series(0, '2014-01-02'::date - '2013-12-15'::date) i
;

3

Giả sử rằng một ngày cuối tuần là thứ bảy và chủ nhật, bạn có thể sử dụng SQL sau.

select count(the_day) from 
    (select generate_series('2014-01-01'::date, '2014-01-10'::date, '1 day') as the_day) days
where extract('dow' from the_day) not in (0,6)

Thay thế ngày bằng các lựa chọn của bạn và (0,6) bằng các ngày trong tuần bạn muốn loại trừ.

Một vài điều bạn cần lưu ý: -

  1. Bạn chưa đề cập đến phiên bản PostgreSQL nào bạn đang chạy. Điều này hoạt động trên 9.1+ nhưng nên hoạt động trên các phiên bản thấp hơn.

  2. Ngày đã chọn được bao gồm khi sử dụng Gener_series. Vì vậy, nếu bạn muốn ngày ở giữa thì thêm 1 ngày cho mỗi ngày.


0

Có một vài điều bạn có thể làm để làm điều này dễ dàng hơn. Phương pháp tôi sẽ sử dụng là đảm bảo có sẵn bảng ngày. Bạn có thể nhanh chóng tạo một cái như vậy:

CREATE TABLE [dbo].[Dates]
(
[Id] INT NOT NULL PRIMARY KEY IDENTITY(0,1),
[Date] Date NOT NULL unique,
isWeekend BIT NOT NULL DEFAULT(0)
)

Khi bảng được tạo, bạn sẽ có thể điền dữ liệu ngày với dữ liệu ngày tương đối nhanh.

set datefirst 6 --start date is saturday
INSERT INTO dbo.Dates(Date, isWeekend)
select 
    Date,
    case datepart(weekday,date) 
        --relies on DateFirst being set to 6
        when 2 then 1 
        when 1 then 1
        else 0
    end as isWeekend
from (
    select 
        dateadd(day, number - 1, 0) as date
    from (
        SELECT top 100000 row_number() over (order by o.object_id) as number
        FROM sys.objects o
            cross join sys.objects b
            cross join sys.objects c
    )numbers
)data

Sau đó, bạn có thể viết truy vấn của mình dưới dạng đếm nhanh các bản ghi từ bảng này.

select count(*) as NumberOfWeekDays
from dbo.dates 
where isWeekend = 0
and date between '1 Jan 2013' and '31 Dec 2013'

0

Tôi đề nghị bạn tạo một hàm để sử dụng bất cứ khi nào bạn muốn và viết ít hơn; )

Mã này ở trên sẽ tạo ra một hàm sql đếm và trả về số ngày cuối tuần (Thứ bảy, Chủ nhật). Chỉ là cách bạn sẽ linh hoạt hơn để sử dụng chức năng này.

CREATE OR REPLACE FUNCTION <YourSchemaNameOptional>.count_full_weekend_days(date, date)
RETURNS bigint AS
$BODY$
        select  COUNT(MySerie.*) as Qtde
        from    (select  CURRENT_DATE + i as Date, EXTRACT(DOW FROM CURRENT_DATE + i) as DiaDate
                 from    generate_series(date ($1) - CURRENT_DATE,  date ($2) - CURRENT_DATE ) i) as MySerie
        WHERE   MySerie.DiaDate in (6,0);
$BODY$
LANGUAGE 'SQL' IMMUTABLE STRICT;

Sau đó, bạn có thể sử dụng chức năng để chỉ trả về số ngày cuối tuần trong một khoảng. Đây là ví dụ để sử dụng:

SELECT <YourSchemaNameOptional>.count_full_weekend_days('2017-09-11', '2017-09-25') as days; --> RES: 4

Lựa chọn này phải trả lại bốn vì ngày đầu tiên và ngày thứ hai là thứ Hai và chúng tôi có 2 ngày thứ Bảy và 2 Chủ nhật giữa chúng.

Bây giờ, để chỉ trả lại ngày làm việc (không có ngày cuối tuần), như bạn muốn , chỉ cần thực hiện một phép trừ, như ví dụ dưới đây:

SELECT (date '2017-09-25' - date '2017-09-11' ) - <YourSchemaName>.count_full_weekend_days('2017-09-11', '2017-09-25'); --> RES: 14 - 4 = 10

-2
-- Returns number of weekdays between two dates
SELECT count(*)  as "numbers of days 
FROM generate_series(0, (‘from_date’::date - 'todate'::date)) i 
WHERE date_part('dow', 'todate'::date + i) NOT IN (0,6)


-- Returns number of weekdays between two dates
SELECT count(*)  as days 
FROM generate_series(0, ('2014/04/30'::date - '2014/04/01'::date)) i 
WHERE date_part('dow', '2014/04/01'::date + i) NOT IN (0,6)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.