tags:

views:

405

answers:

5

I have a table with rows that symbolize order dates:

2009-05-15 13:31:47.713 
2009-05-15 22:09:32.227
2009-05-16 02:38:36.027
2009-05-16 12:06:49.743
2009-05-16 16:20:26.680
2009-05-17 01:36:19.480
2009-05-18 09:44:46.993
2009-05-18 14:06:12.073 
2009-05-18 15:25:47.540
2009-05-19 10:28:24.150

I would like have query that returns the following:

2009-05-15 2
2009-05-16 5
2009-05-17 6
2009-05-18 9
2009-05-19 10

Basically it keeps a running total of all the orders placed by the end of the day of the date indicated. The orders are not the orders on that day but all the orders since the earliest dates in the table.

This is MSSQL 2000 and the datatype in the first table is just datetime, in the second it could be datetime or string, it doesn't really matter for my purposes.

A: 

Try this (returns string dates):

SELECT
    LEFT(CONVERT(char(23),YourDate,121),10) AS Date
        ,COUNT(*) AS CountOf
    FROM YourTable
    GROUP BY LEFT(CONVERT(char(23),YourDate,121),10) 
    ORDER BY 1

this will table scan. if it is too slow, consider using a persistant computed column with an index for the date, that will run much faster. However, I'mnot sure if you can do all that in SQL 2000.

EDIT read the question better, try this:

SELECT
    d.YourDate
        ,SUM(dt.CountOf) AS CountOf
    FROM (SELECT
              LEFT(CONVERT(char(23),YourDate,121),10) AS Date
                  ,COUNT(*) AS CountOf
              FROM YourTable
              GROUP BY LEFT(CONVERT(char(23),YourDate,121),10) 
        ) dt
        INNER JOIN (SELECT
                        DISTINCT LEFT(CONVERT(char(23),YourDate,121),10) AS Date
                        FROM YourTable
                   ) d ON dt.Date<=LEFT(CONVERT(char(23),d.YourDate,121),10)
    GROUP BY d.YourDate
    ORDER BY d.YourDate
KM
That's going to give count by Day, not count of all things before day any given day.
Russell Steen
@Russell Steen, thanks, I read the question better, see edit does what OP wants.
KM
A: 

SELECT Count(*), LEFT(CONVERT(char(23),YourDate,121),10) AS Date FROM
(SELECT
DISTINCT LEFT(CONVERT(char(23),YourDate,121),10) AS Date
FROM YourTable
GROUP BY LEFT(CONVERT(char(23),YourDate,121),10)) x //Gets the distinct dates.
INNER JOIN YourTable y on x.Date >= y.Date
GROUP BY LEFT(CONVERT(char(23),YourDate,121),10)

It's going to be slow. REALLY REALLY slow. I hate to think what run times would be.

Russell Steen
// is not a tsql comment, use --
KM
your version is slow, it took 1:19 to return 2,402 rows from a table of 368,449, where mine took 2 seconds to return 2043 rows. your version is reports one day off (the count shown is for previous date) and you miss the last day.
KM
I used // under the mistaken impression that it would show up green in the stackoverflow display. I know my version is slow. Your edits weren't up when I was writing it and I was trying to get him going on the query. Your version looks good after the edits.
Russell Steen
I actually thought my version would run much slower than it did. @JamesMLV version runs in the same 2 secs as mine, but I like his better, more compact.
KM
Great! Thanks for validating that for everyone
Russell Steen
Mine also has an unnecessary Group by clause in my inner select query.
Russell Steen
+1  A: 

I recommend a 2 query solution. This is slow, but I use this method almost daily. The important thing is to NOT join the 2 tables in the first query. You want the duplication of each order for every date in your lookup table.

You will need a Lookup table with 1 row for each date of the time period you're interested in. Let's call it dboDateLookup. Here's what it will look like:

DtIndex
2009-05-15
2009-05-16
2009-05-17
2009-05-18
2009-05-19

Let's also assume the order table, dboOrders has 2 columns, ordernumber and orderdate. ordernumber orderdate
2009-05-15 13:31:47.713 1
2009-05-15 22:09:32.227 2
2009-05-16 02:38:36.027 3
2009-05-16 12:06:49.743 4
2009-05-16 16:20:26.680 5

Query1:
SELECT
Format([ordernumber],"yyyy-mm-dd") AS ByDate,
ordernumber,
(If Format([orderdate],"yyyy-mm-dd")<=[DtIndex],1,0) AS NumOrdersBefore
FROM [dboOrders], [dboDateLookUp];

Query2:
Select
[ByDate],
sum([NumOrdersBefore]) as RunningTotal
from [Query1];

PowerUser
_FORMAT()_ is not a tsql command or function
KM
+5  A: 

I got this to work on SQL Server 2005. I think it should work with 2000, as well.

SELECT dt, count(q2.YourDate)
    FROM (SELECT DISTINCT CONVERT(varchar,YourDate,101) dt FROM YourTable) t1
    JOIN YourTable q2 ON DATEADD(d,-1,CONVERT(varchar,YourDate,101)) < dt
    GROUP BY dt

This will query the table twice, but at least gives correct output.

JamesMLV
That did it! Thanks!
Matt
+1, same basic join solution as mine, but without the extra derived table. nice compact solution!
KM
+1 here too, same basic join solution as mine as well, but much more compact and Tsql specific to boot.
PowerUser
A: 

I have another one It is not so fancy I ran it on Access so syntax may differ little bit. But it seems to work.

P.S. Im relatively new to SQL

Data:

ID  F1 F2
1   15/05/2009 13:31:47.713
2   15/05/2009 22:09:32.227
3   16/05/2009 02:38:36.027
4   16/05/2009 12:06:49.743
5   16/05/2009 16:20:26.680
6   17/05/2009 01:36:19.480
7   18/05/2009 09:44:46.993
8   18/05/2009 14:06:12.073
9   18/05/2009 15:25:47.540
10  19/05/2009 10:28:24.150

Query:

SELECT Table1.F1 AS Dates, SUM(REPLACE(Len(Table1.F2), Len(Table1.F2), 1)) AS Occurred
FROM Table1
GROUP BY Table1.F1;

Result:

Dates   Occurred
15/05/2009  2
16/05/2009  3
17/05/2009  1
18/05/2009  3
19/05/2009  1