all groups > sql server programming > july 2006 >
You're in the

sql server programming

group:

tricky query?


Re: tricky query? Alexander Kuznetsov
7/12/2006 2:42:17 PM
sql server programming:
Lisa,

you need to use a calendar table, as follows:

select * from calendar order by d

d
------------------------------------------------------
2006-01-01 00:00:00.000
2006-01-02 00:00:00.000
2006-01-03 00:00:00.000
2006-01-04 00:00:00.000
2006-01-05 00:00:00.000

(snip)

search on aspfaq.com for a great explanation on setting up a calendar
table.
Having a calendar table, your query is a snap:

insert into additions values('20060101', 100)
insert into additions values('20060201', 100)
insert into additions values('20060401', 100)
insert into additions values('20060501', 100)
insert into unloads values('20060315', 100)

select d,
(select count(*) from additions a where a.logdatetime < d and not
exists(
select 1 from unloads u where u.logdatetime between a.logdatetime and
d
)
) cnt
from calendar order by d

d cnt
------------------------------------------------------ -----------
2006-01-01 00:00:00.000 0
2006-01-02 00:00:00.000 1
2006-01-03 00:00:00.000 1

(snip)

2006-01-31 00:00:00.000 1
2006-02-01 00:00:00.000 1
2006-02-02 00:00:00.000 2
2006-02-03 00:00:00.000 2

(snip)

2006-03-13 00:00:00.000 2
2006-03-14 00:00:00.000 2
2006-03-15 00:00:00.000 0
2006-03-16 00:00:00.000 0

(snip)

2006-03-31 00:00:00.000 0
2006-04-01 00:00:00.000 0
2006-04-02 00:00:00.000 1
2006-04-03 00:00:00.000 1

(snip)

2006-04-30 00:00:00.000 1
2006-05-01 00:00:00.000 1
2006-05-02 00:00:00.000 2
2006-05-03 00:00:00.000 2

(snip)
Re: tricky query? Arnie Rowland
7/12/2006 4:50:09 PM
Check out this information about using a Calendar table.

http://www.aspfaq.com/show.asp?id=2519
--
Arnie Rowland*
"To be successful, your heart must accompany your knowledge."




[quoted text, click to view]

Re: tricky query? Roy Harvey
7/12/2006 5:51:07 PM
You need a calendar table. I also assumed the existince of a Boxes
table, one row for each boxnumber.

This is an attempt to handle the "any range of dates" version. It is
untested.

SELECT C.CalDate as logdate,
B.boxnumber,
(select count(*) from additions as A
where A.boxnumber = B.boxnumber
and A.logdatetime <= C.CalDate
and A.logdatetime >
(select max(logdatetime) from unloads as U
where U.boxnumber = B.boxnumber
and U.A.logdatetime <= C.CalDate))
FROM Boxes as B
CROSS JOIN Calendar as C
WHERE C.CalDate between '1 Jan 2006' and '31 Mar 2006'

Roy Harvey
Beacon Falls, CT

On Wed, 12 Jul 2006 23:03:54 +0200, "Lisa Pearlson" <no@spam.plz>
[quoted text, click to view]
RE: tricky query? Omnibuzz
7/12/2006 10:21:02 PM
Hi,
Juz in case you don't want to use a calender table and want the result to
be generated for each of the boxnumber, you can try something like this (I
have added a few more rows to include mutiple box numbers)

/*
insert into additions values('20060104', 200)
insert into additions values('20060204', 200)
insert into additions values('20060404', 200)
insert into additions values('20060504', 200)
insert into unloads values('20060320', 200)

*/

declare @start datetime,
@end datetime

set @start = '2006-01-01'
set @end = '2006-05-02'

declare @no_of_Days int
set @no_of_days = datediff(dd,@start,@end) + 1

set rowcount @no_of_days

select identity(int,0,1) as dy into #temp from sysobjects a, sysobjects b

set rowcount 0

select boxnumber, @start + dy as chkdate, sum(case when
logdatetime <= @start + dy then isadd else 0 end) from #temp,
(select logdatetime,boxnumber, 1 as isadd from additions
union all
select logdatetime,boxnumber, -1 as isadd from unloads
) as b
where @start + dy <= @end
group by boxnumber, dy
order by boxnumber,dy

drop table #temp


Hope this helps.
--
-Omnibuzz (The SQL GC)

http://omnibuzz-sql.blogspot.com/
tricky query? Lisa Pearlson
7/12/2006 11:03:54 PM
Hi,

Imagine I have 2 different tables, keeping a log of additions of items to
some container, and another that keeps a log of when those containers were
emptied.

For example, simplified:

CREATE TABLE additions (
logdatetime DATETIME NOT NULL,
boxnumber INT NOT NULL
);

CREATE TABLE unloads (
logdatetime DATETIME NOT NULL,
boxnumber INT NOT NULL
);

Imagine these represent a box that items are put in.. each time an item is
put into this box, a log is collected, and once in a while, the log, kept by
a hardware device, is sent to the database via a communications interface.
This means that in a short time, several INSERT's are made into additions..
once in a while, the box is emptied, and this ends up being logged in the
second table.. explaining why these types of data are not put in the same
table, is a different story I do not with to elaborate on. But there's a
good enough reason for it.

Now imagine the contents of these tables being something like this:

table additions:
logdatetime boxnumber
2006-01-01 12:00:00 100
2006-02-01 12:00:00 100
2006-04-01 12:00:00 100
2006-05-01 12:00:00 100

table unloads (empty events):
2006-03-15 12:00:00 100


So in january, february, april and may there were additions, but on march
the container was emptied.
In reality, there are several events every day.. what I need now is to
display for each day the total number of items in a a container. So I have
to add up the additions to know how many items there were at any particular
date, (including dates on which there were no events at all).

So on May 10th, for example, there were 2 items . But on May 16 there were
0, because on May 15, there was an unload event, that emptied the whole
container.

How do I put this in a query?
I'm guessing first I join both tables in a SELECT .. UNION SELECT ..
statement, then sort it on logdate, so I have a chronological list of
events:
SELECT * FROM (SELECT logdatetime,boxnumber,'added' FROM additions
UNION
SELECT logdatetime,boxnumber,'flush' FROM unloads) x ORDER BY logdatetime

logdatetime boxnumber type
2006-01-01 12:00:00 100 added <-- box 100 has 1 item
2006-02-01 12:00:00 100 added <-- box 100 has 2 items
2006-03-15 12:00:00 100 flush <-- box 100 has 0 items
2006-04-01 12:00:00 100 added <-- box 100 has 1 item
2006-05-01 12:00:00 100 added <-- box 100 has 2 items

Now, I need to create a query that lists all items, as sums of previous
items (incremental) up until the previous flush:

logdatetime boxnumber totals
2006-01-01 12:00:00 100 1
2006-02-01 12:00:00 100 2
2006-03-15 12:00:00 100 0
2006-04-01 12:00:00 100 1
2006-05-01 12:00:00 100 2

Such query would already help me out a lot, but additionally, if possible, I
would like to be able to select ANY range of dates, and have a totals
displayed for EACH DAY.. whether actual records exist on this day or not.

So, looking at period 2006-01-01 until 2006-01-07:

logdata boxnumber totals
2006-01-01 00:00:00 100 0 <-- prior to 12:00
2006-01-02 00:00:00 100 1 <-- since 2006-01-01 12:00:00
2006-01-03 00:00:00 100 1
2006-01-04 00:00:00 100 1
2006-01-05 00:00:00 100 1
2006-01-06 00:00:00 100 1
2006-01-07 00:00:00 100 1


So, how do I incrementally count up the totals for all recent additions,
since the last flush?

Lisa

AddThis Social Bookmark Button