Domanda

The Problem: Given a day of the week (1, 2, 3, 4, 5, 6, 7), a starting date and an ending date, compute the number of times the given day of the week appears between the starting and ending dates not inclusive of a date for which there were no sales.

Context:

Table "Ticket" has the following structure and sample content:

i_ticket_id c_items_total      dt_create_time       dt_close_time
----------------------------------------------------------------------------
1        8.50       '10/1/2012 10:23:00'    '10/1/2012 11:05:05'
2       10.50       '10/1/2012 11:00:00'    '10/1/2012 11:45:05'
3        8.50       '10/2/2012 08:00:00'    '10/2/2012 09:25:05'
4        8.50       '10/4/2012 08:00:00'    '10/4/2012 09:25:05'
5        7.50       '10/5/2012 13:22:23'    '10/5/2012 14:33:27'
.
.
233      6.75       '10/31/2012 23:20:00'   '10/31/2012 23:55:39'

Details

  1. There may or may not be any tickets for one or more days during a month. (i.e. the place was closed that/those day/s)

  2. Days in which the business is closed are not regular. There is no predictable pattern.

Based on Get number of weekdays (Sundays, Mondays, Tuesdays) between two dates SQL, I have derived a query which returns the number of times a given day of the week occurs between the start date and the end date:

DECLARE @dtStart DATETIME = '10/1/2013 04:00:00'
DECLARE @dtEnd DATETIME = '11/1/2013 03:59:00'
DECLARE @day_number INTEGER = 1
DECLARE @numdays INTEGER

SET @numdays = (SELECT 1 + DATEDIFF(wk, @dtStart, @dtEnd)-
CASE WHEN DATEPART(weekday, @dtStart)  @day_number THEN 1 ELSE 0 END -
CASE WHEN DATEPART(weekday, @dtEnd) <= @day_number THEN 1 ELSE 0 END)

Now I just need to filter this so that any zero-dollar days are not included in the count. Any help you can provide to add this filter based on the contents of the tickets table is greatly appreciated!

È stato utile?

Soluzione

If I understand correctly, you can use a calendar table to count the number of days where the day of week is n and between the start and end and is a date that has ticket sales, which I guess is when the date exists in tickets and has the sum(c_items_total) > 0

WITH cal AS 
(
  SELECT cast('2012-01-01' AS DATE) dt, datepart(weekday, '2012-01-01') dow
  UNION ALL      
  SELECT dateadd(day, 1, dt), datepart(weekday, dateadd(day, 1, dt))
  FROM cal
  WHERE dt < getdate()
)

SELECT COUNT(1)
FROM cal
WHERE dow = 5 
  AND dt BETWEEN '2012-04-01' AND '2012-12-31'
  AND EXISTS (
    SELECT 1
    FROM tickets
    WHERE cast(dt_create_time AS DATE) = dt
    GROUP BY cast(dt_create_time AS DATE)
    HAVING sum(c_items_total) > 0
    )
OPTION (MAXRECURSION 0)

SQLFiddle

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top