Showing posts with label records. Show all posts
Showing posts with label records. Show all posts

Friday, March 30, 2012

How to exclude duplicate records from totals

My column figures are correct in my report, but duplicate values are being added to the totals.

I am using:

Format(Sum(Fields!ACEG_Contribution.Value), "C")

This is not a matrix report. I am using tables so it only has table headers and table footers.

How can I fix this? Please advise a-sap.

Thanx in advance for any assistance you can provide,

gb

Hi Gerry-

Not completly certain where your duplication is coming from - as per your description. If duplicate values are present in your data, you would want to use the DISTINCT clause in your query to filter duplicates.

If you have groupings in your table, and want to subtotal rather than grandtotal, you can use the scope argument on the SUM function to filter per group i.e. Sum(Fields!Value, "Group1)".

If you want to display duplicates, bu only sum the non-duplicates, you would need to have a separate query which uses the DISTINCT caluse, then create an expression in your table footer which does sum of second dataset. i.e. SUM(Fields!Value, "DataSet2")

Hope that helps,

Thanks, Jon

Wednesday, March 28, 2012

How to ensure the rest of the records will be inserted even if there is an error

Hi,
I have a sql statement that perform bulk insert into another table.
How can I ensure that if an error occurs, maybe due to primary key
constraint, the rest of the records will be inserted.
Thanks alot.Hi
Take a look at this example, even this transaction will generate a violation
of primary key constraint the rest of the data will be inserted
Please read SET ARITHABORT commant in the BOL to get a whole picture
create table #t (col int not null primary key)
begin tran
insert into #t values (1)
insert into #t values (2)
insert into #t values (3)
insert into #t values (3)
insert into #t values (4)
insert into #t values (5)
commit
select * from #t
drop table #t
"Shelby" <shelby@.singnet.com.sg> wrote in message
news:%23X6PcA6XGHA.3868@.TK2MSFTNGP04.phx.gbl...
> Hi,
> I have a sql statement that perform bulk insert into another table.
> How can I ensure that if an error occurs, maybe due to primary key
> constraint, the rest of the records will be inserted.
> Thanks alot.
>
>
>|||That depends on the type of error that occures. Fatal Errrors for
example will always abort the entire procedure and rollback all
transactions. There might be a way for non-fatal errors using if-blocks
like
if @.err<>0
// do something else with the datasql

How to enhance the performance of a table

hi i have table with around 15 fields and has a pk.
there're some web applications will insert records into it. there're some
backgroup application will query the table.
now, i have around 1000 thousand records, but the there're some locking
behaviour, and even i go query analyzer and do simple query search, i have
the timeout error.
how can i simply improve the performance of it?
thanks!
mullinHi,
how can i simply improve the performance of it?
Create Indexes based on the Where clause of your query. This will definetely
speed up your queries.
How to reduce locks:
1. Create necessary indexes
2. Make the transaction as short as possible.
3. Might be I/O bottle neck.
Whenever your server experiences an I/O bottleneck, the longer it takes
user's transactions to complete.
And the longer they take to complete, the longer locks must be held, which
can lead to other transactions
having to wait for previous locks to be released.
Thanks
Hari
MCDBA
"Mullin Yu" <mullin_yu@.ctil.com> wrote in message
news:uqbTi72JEHA.2576@.TK2MSFTNGP12.phx.gbl...
> hi i have table with around 15 fields and has a pk.
> there're some web applications will insert records into it. there're some
> backgroup application will query the table.
> now, i have around 1000 thousand records, but the there're some locking
> behaviour, and even i go query analyzer and do simple query search, i have
> the timeout error.
> how can i simply improve the performance of it?
> thanks!
> mullin
>

How to enhance the performance of a table

hi i have table with around 15 fields and has a pk.
there're some web applications will insert records into it. there're some
backgroup application will query the table.
now, i have around 1000 thousand records, but the there're some locking
behaviour, and even i go query analyzer and do simple query search, i have
the timeout error.
how can i simply improve the performance of it?
thanks!
mullinHi,
how can i simply improve the performance of it?
Create Indexes based on the Where clause of your query. This will definetely
speed up your queries.
How to reduce locks:
1. Create necessary indexes
2. Make the transaction as short as possible.
3. Might be I/O bottle neck.
Whenever your server experiences an I/O bottleneck, the longer it takes
user's transactions to complete.
And the longer they take to complete, the longer locks must be held, which
can lead to other transactions
having to wait for previous locks to be released.
Thanks
Hari
MCDBA
"Mullin Yu" <mullin_yu@.ctil.com> wrote in message
news:uqbTi72JEHA.2576@.TK2MSFTNGP12.phx.gbl...
> hi i have table with around 15 fields and has a pk.
> there're some web applications will insert records into it. there're some
> backgroup application will query the table.
> now, i have around 1000 thousand records, but the there're some locking
> behaviour, and even i go query analyzer and do simple query search, i have
> the timeout error.
> how can i simply improve the performance of it?
> thanks!
> mullin
>

How to enhance the performance of a table

hi i have table with around 15 fields and has a pk.
there're some web applications will insert records into it. there're some
backgroup application will query the table.
now, i have around 1000 thousand records, but the there're some locking
behaviour, and even i go query analyzer and do simple query search, i have
the timeout error.
how can i simply improve the performance of it?
thanks!
mullin
Hi,
how can i simply improve the performance of it?
Create Indexes based on the Where clause of your query. This will definetely
speed up your queries.
How to reduce locks:
1. Create necessary indexes
2. Make the transaction as short as possible.
3. Might be I/O bottle neck.
Whenever your server experiences an I/O bottleneck, the longer it takes
user's transactions to complete.
And the longer they take to complete, the longer locks must be held, which
can lead to other transactions
having to wait for previous locks to be released.
Thanks
Hari
MCDBA
"Mullin Yu" <mullin_yu@.ctil.com> wrote in message
news:uqbTi72JEHA.2576@.TK2MSFTNGP12.phx.gbl...
> hi i have table with around 15 fields and has a pk.
> there're some web applications will insert records into it. there're some
> backgroup application will query the table.
> now, i have around 1000 thousand records, but the there're some locking
> behaviour, and even i go query analyzer and do simple query search, i have
> the timeout error.
> how can i simply improve the performance of it?
> thanks!
> mullin
>

how to enforce a trigger when update for each record when updates several records bulky?

I made a trigger on a table that fires when update happens, the trigger fires when attempting to update a single record (that is normally) but when trying to update several records bulky using one update statement it fires only once either.

My question is, how to enforce firing the trigger for each record when updates bulky? i.e. how to ensure that when I use the following update statement

UPDATE MyTableName SET ColumnName = 5

And there are 10 records that affected; that the trigger would fire 10 times? (I have the fact that it fires only once)

In SQL server, a trigger fires once per statement, not per row and this can not be changed. You must write your trigger to be able to handle a multiple row update. Post your trigger code and likely someone here can help you re-write it to work for multiple row updates.|||Thanks David, your reply was helpfulsql

Monday, March 26, 2012

how to encrypt my password or sensitive data before storing them in a database , using SQL

Hi there ,

1. i have a database and i want to encrypt my passwords before storing my records in a database plus i will later on would require to authenticate my user so again i have to encrypt the string provided by him to compare it with my encrypted password in database

below is my code , i dont know how to do it , plz help

2. one thing more i am storing IP addresses of my users as a "varchar" is there a better method to do it , if yes plz help me

try
{
SqlConnection myConnection = new SqlConnection();
myConnection.ConnectionString = ConfigurationManager.ConnectionStrings["projectConnectionString"].ConnectionString;

SqlDataAdapter myAdapter = new SqlDataAdapter("SELECT *From User_Info", myConnection);
SqlCommandBuilder builder = new SqlCommandBuilder(myAdapter);
DataSet myDataset = new DataSet();
myAdapter.Fill(myDataset, "User_Info");

//Adding New Row in User_Info Table
DataRow myRow = myDataset.Tables["User_Info"].NewRow();
myRow["user_name"] = this.user_name.Text;
myRow["password"] = this.password.Text; // shoule be encrypted
//not known till now how to do it

myRow["name"] = this.name.Text;
myRow["ip_address"] = this.ip_address.Text;

myDataset.Tables["User_Info"].Rows.Add(myRow);
myAdapter.Update(myDataset, "User_Info");

myConnection.Close();
myConnection.Dispose();

}
catch (Exception ex)
{
this.error.Text = "Error ocurred in Creating User : " + ex.Message;
}

Hello my friend, I will give you the answer to this.

Firstly, run the following SQL to create the encrypt function: -

CREATE FUNCTION fn_AlterString
(
@.String AS VARCHAR(800),
@.Key AS VARCHAR(80),
@.Direction AS BIT
)

RETURNS VARCHAR(800)

AS

BEGIN

DECLARE @.NewString AS VARCHAR(800)
SET @.NewString = ''

DECLARE @.Keyi AS INT
SET @.Keyi = 1

DECLARE @.i AS INT
SET @.i = 1

WHILE @.i <= LEN(@.String)
BEGIN
IF (@.Direction = 1)
BEGIN
SET @.NewString = @.NewString + CHAR(ASCII(SUBSTRING(@.String, @.i, 1))
+ CAST(SUBSTRING(@.Key, @.Keyi, 1) AS INT))
END
ELSE BEGIN
SET @.NewString = @.NewString + CHAR(ASCII(SUBSTRING(@.String, @.i, 1))
- CAST(SUBSTRING(@.Key, @.Keyi, 1) AS INT))
END

IF @.Keyi < LEN(@.Key)
BEGIN
SET @.Keyi = @.Keyi + 1
END
ELSE BEGIN
SET @.Keyi = 1
END

SET @.i = @.i + 1
END

RETURN @.NewString

END

Now run the following SQL that will create a stored procedure that your web page will use: -

CREATE PROCEDURE usp_InsertUser
(
@.UserName AS VARCHAR(50),
@.Password AS VARCHAR(50),
@.Key AS VARCHAR(80)
)

AS

INSERT INTO User_Info
( [User_Name],
[Password]
)
VALUES
( @.UserName,
dbo.fn_AlterString(@.Password, @.Key, 1)
)

RETURN

Now alter your web page code as follows: -

SqlConnection

conn =newSqlConnection(ConfigurationManager.ConnectionStrings["projectConnectionString"].ConnectionString);SqlCommand cmd =newSqlCommand("usp_InsertUser", conn);

cmd.CommandType =

CommandType.StoredProcedure;// change these as you see fit

cmd.Parameters.Add(

"@.UserName","test");

cmd.Parameters.Add(

"@.Password","havinggoodday");// ideally, this key should be stored in the web.config file

cmd.Parameters.Add(

"@.Key","564335567754326769012342896");

cmd.ExecuteNonQuery();

conn.Close();

Now for an explanation. The fn_AlterString() function takes a string and transforms it into another based on the second parameter, the key. The third parameter is 1 to encrypt and 0 to decrypt.

Therefore: -

SELECT dbo.fn_AlterString('havinggoodday', '564335567754326769012342896', 1) gives you mgzlqlluvkie|

SELECT dbo.fn_AlterString('mgzlqlluvkie|', '564335567754326769012342896', 0) gives you havinggoodday

You will need to do the latter when checking the password of the user when they log in.

Obviously you will need to use the same key when encrypting and decrypting. They key can only contain numbers. The more digits, the more secure. You can have a larger key than the one used but I put an 80 limit in the function parameter, which you can extend. The key is passed to the stored procedure and in turn passed to the function then used within it, so if somebody stole your database data, your stored procedure code and function code they still would not be able to read your encrypted data because they would need the key, which I suggest you put in the web.config file.

As for your second question, using a varchar to store an ip address is fine. If you need any more help, let me know.

Kind regards

Scotty

|||

hi thanks for your kind help ,

i haven't seen anyone that cool to write an entire code for somebody for free , i appreciate that

one more thing :

can you please tell me how to store and retrieve the key for encryption from web.config file

best regards

gurpreet

|||

Hi Gurpreet,

Within the web.config file add the following within the appSettings section: -

<

appSettings>

<

addkey="VisitationsExpected"value="45545454545445544554"/>

</

appSettings>

Notice the name I have chosen? Call it anything but decryption key. Then within your page code: -

string

strKey =ConfigurationSettings.AppSettings["VisitationsExpected"];

Thanks for the appreciation. I do not appreciate it when users leave one line answers and expect you to know what they mean exactly to fit your situation. I like to take a task to completion. All I ask is that you mark me as the answerer for your question. If you have any more problems, put them in the forum and send me a private message so I am made aware of it.

Kind regards

Scotty

sql

How to encorporate IF

How can I put an If statement saying If # RECORDS returned from the query below
IF # records returned is > 1 then
SUM(rmstranamt) AS rmstranamt10
ELSE
rmstranamt AS rmstranamt10

here's my statement

-


SELECT RMSFILENUM,
rmstranamt AS rmstranamt10 <--If statement goes here base on if the amount of records found in select is >1 or not
FROM RFINANL
WHERE RMSTRANCDE = '10'
GROUP BY RMSFILENUM, rmstranamt
) AS rf10 ON rf10.RMSFILENUM = rm.RMSFILENUM

I want to return sum(rmstranamt) AS rmstranamt10 in cases where the same query produces > 1 records
In other words if this:
SELECT RMSFILENUM,
rmstranamt AS rmstranamt10
FROM RFINANL
WHERE RMSTRANCDE = '10'
GROUP BY RMSFILENUM, rmstranamt
produces > 1 records, then I don't want to return rmstranamt AS rmstranamt10, I want to return sum(rmstranamt) AS rmstranamt10

Wouldn't

SUM(rmstranamt)
be the same as
rmstranamt

in the case of one record? Think you should just include the sum and not worry about it.

- Brad
|||

you would think....I've spent 3 days on this...check it out more here:

http://www.experts-exchange.com/Databases/Microsoft_SQL_Server/Q_21692997.html

|||I see your issue now, but the problem isn't the SUM function rather the GROUP BY clause.

Just remmove the rmstranamt from your GROUP BY to achieve the desired results, otherwise each row returned represents a SUM applied to a GROUP that has one row.

- Brad|||Brad, you mean remove rmstranamt from my last Group By right? If I do that then It errors out saying that rmstranamt needs to be in it...so what do I do?|||Brad, ok yes, that works but to a certain point. My main problem is when I plug in an account that I know has more than 1 results from my first INNER JOIN query, it throws off my end aggregation and I end up with 2 account rows rather than one for that account|||SELECT RMSFILENUM, sum(rmstranamt) rmstranamt10
FROM RFINANL
WHERE RMSTRANCDE = '10'
GROUP BY RMSFILENUM|||

Hi,

SELECT RMSFILENUM
into #tmp

FROM RFINANL
WHERE RMSTRANCDE = '10'
GROUP BY RMSFILENUM having count(rmstranamt) <= 1

SELECT RMSFILENUM,
sum(rmstranamt )AS rmstranamt10

FROM RFINANL
WHERE RMSTRANCDE = '10'
GROUP BY RMSFILENUM having count(rmstranamt) > 1

union

SELECT r.RMSFILENUM,
rmstranamt AS rmstranamt10

FROM RFINANL r inner join #tmp t on r.RMSFILENUM = t.RMSFILENUM
GROUP BY r.RMSFILENUM, r.rmstranamt

Regards

How to encorporate IF

How can I put an If statement saying If # RECORDS returned from the query below
IF # records returned is > 1 then
SUM(rmstranamt) AS rmstranamt10
ELSE
rmstranamt AS rmstranamt10

here's my statement

-


SELECT RMSFILENUM,
rmstranamt AS rmstranamt10 <--If statement goes here base on if the amount of records found in select is >1 or not
FROM RFINANL
WHERE RMSTRANCDE = '10'
GROUP BY RMSFILENUM, rmstranamt
) AS rf10 ON rf10.RMSFILENUM = rm.RMSFILENUM

I want to return sum(rmstranamt) AS rmstranamt10 in cases where the same query produces > 1 records
In other words if this:
SELECT RMSFILENUM,
rmstranamt AS rmstranamt10
FROM RFINANL
WHERE RMSTRANCDE = '10'
GROUP BY RMSFILENUM, rmstranamt
produces > 1 records, then I don't want to return rmstranamt AS rmstranamt10, I want to return sum(rmstranamt) AS rmstranamt10

Wouldn't

SUM(rmstranamt)
be the same as
rmstranamt

in the case of one record? Think you should just include the sum and not worry about it.

- Brad
|||

you would think....I've spent 3 days on this...check it out more here:

http://www.experts-exchange.com/Databases/Microsoft_SQL_Server/Q_21692997.html

|||I see your issue now, but the problem isn't the SUM function rather the GROUP BY clause.

Just remmove the rmstranamt from your GROUP BY to achieve the desired results, otherwise each row returned represents a SUM applied to a GROUP that has one row.

- Brad|||Brad, you mean remove rmstranamt from my last Group By right? If I do that then It errors out saying that rmstranamt needs to be in it...so what do I do?|||Brad, ok yes, that works but to a certain point. My main problem is when I plug in an account that I know has more than 1 results from my first INNER JOIN query, it throws off my end aggregation and I end up with 2 account rows rather than one for that account|||SELECT RMSFILENUM, sum(rmstranamt) rmstranamt10
FROM RFINANL
WHERE RMSTRANCDE = '10'
GROUP BY RMSFILENUM|||

Hi,

SELECT RMSFILENUM
into #tmp

FROM RFINANL
WHERE RMSTRANCDE = '10'
GROUP BY RMSFILENUM having count(rmstranamt) <= 1

SELECT RMSFILENUM,
sum(rmstranamt )AS rmstranamt10

FROM RFINANL
WHERE RMSTRANCDE = '10'
GROUP BY RMSFILENUM having count(rmstranamt) > 1

union

SELECT r.RMSFILENUM,
rmstranamt AS rmstranamt10

FROM RFINANL r inner join #tmp t on r.RMSFILENUM = t.RMSFILENUM
GROUP BY r.RMSFILENUM, r.rmstranamt

Regards

Monday, March 19, 2012

How to Dynamically Generate FileName using SSIS

Hi

I have generated a ssis package that creates a text file based on a query retrieving records from the table.

Now i want the file name to be appended with the date and time of package execution. So the filename will be something like ; Filename_MMDDYYYY.txt.

How can i do this with the help of SSIS?

Anyone having an idea would be of great help.

Regards,

Salman Shehbaz.

Have a look at expressions.|||

for me the following link did the magic;

http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=932686&SiteID=1

Wednesday, March 7, 2012

How to do this SQL analysis...

With SQL 2005 Standard: I have records in a table that show how long it
takes to complete a task...
ID_KEY DATETIME (nearest minute) DURATION
When a task is started, a record is added with a "null" duration, and when
the task is finished, the duration is updated to represent the number of
seconds the task took to complete. So, here's sample values:
133541 2006-02-27 16:51:00 NULL
133540 2006-02-27 16:51:00 60
133539 2006-02-27 16:50:00 NULL
133538 2006-02-27 16:50:00 153
133537 2006-02-27 16:50:00 30
The above data shows that 2 tasks are not complete and 3 tasks finished in
those respective #seconds.
My question: I would like to know how to determine the number of
simulataneous tasks in process for any given period of time, or by the hour
of the day. Right this moment, I can determine that by doing SELECT
COUNT(*) FROM TABLE WHERE DURATION IS NULL, but once you get into the
historical perspective (where the nulls are all real duration values), you
have to figure our which duration values overlap with other duration values.
Yeah, I know my full-minute rounding will screw up the analysis, but coming
close would be nice right now. For example, the 153 second task was
simultaneous with the two tasks that started one minute later. But how do
you run some kind of query against the table for periods of time where the
durations are all now complete (no nulls for yesterday, for example, because
those tasks are complete). How do I determine those "max simultaneous tasks
were in progress" during hour by hour windows of time? Or something like
that? I really need this to determine staffing, because if we had 100
simulatenous tasks between 8 and 8:10 AM yesterday morning, I know we need
to hire more people.
"HK" <replywithingroup@.notreal.com> wrote in message
news:8kGMf.2874$xS5.921@.tornado.socal.rr.com...
> With SQL 2005 Standard: I have records in a table that show how long it
> takes to complete a task...
> ID_KEY DATETIME (nearest minute) DURATION
> When a task is started, a record is added with a "null" duration, and when
> the task is finished, the duration is updated to represent the number of
> seconds the task took to complete. So, here's sample values:
> 133541 2006-02-27 16:51:00 NULL
> 133540 2006-02-27 16:51:00 60
> 133539 2006-02-27 16:50:00 NULL
> 133538 2006-02-27 16:50:00 153
> 133537 2006-02-27 16:50:00 30
> The above data shows that 2 tasks are not complete and 3 tasks finished in
> those respective #seconds.
>
How about doing a DATEADD on the seconds for completed tasks as a time2 in
the query, then select BETWEEN time1 and time2.
Rick Sawtell
MCT, MCSD, MCDBA
|||"Rick Sawtell" <Quickening@.msn.com> wrote in message
news:%23BssXF8OGHA.3728@.tk2msftngp13.phx.gbl...[vbcol=seagreen]
> "HK" <replywithingroup@.notreal.com> wrote in message
> news:8kGMf.2874$xS5.921@.tornado.socal.rr.com...
when[vbcol=seagreen]
in
> How about doing a DATEADD on the seconds for completed tasks as a time2 in
> the query, then select BETWEEN time1 and time2.
> Rick Sawtell
> MCT, MCSD, MCDBA
>
>
>
Although I understand the concept and how to use date functions, I still
don't know how to put this into production in a real query (the selecting
count between time1 and time2 is still not clear when I try), and also how
to group by time intervals. Sample syntax would be much appreciated.
Thanks.
|||> When a task is started, a record is added with a "null" duration, and when
> the task is finished, the duration is updated to represent the number of
> seconds the task took to complete. So, here's sample values:
> 133541 2006-02-27 16:51:00 NULL
> 133540 2006-02-27 16:51:00 60
> 133539 2006-02-27 16:50:00 NULL
> 133538 2006-02-27 16:50:00 153
> 133537 2006-02-27 16:50:00 30
> The above data shows that 2 tasks are not complete and 3 tasks finished in
> those respective #seconds.
I assume you realize why this task is so difficult. For those who don't,
this is what happens when the schema is not properly normalized. In this
case, I am assuming that there is a 1-1 relationship between the "start" row
of a given task and the "end" row of a given task - both are related by a
common value for ID_KEY. Comments below are predicated on these
assumptions.

> My question: I would like to know how to determine the number of
> simulataneous tasks in process for any given period of time, or by the
> hour
> of the day. Right this moment, I can determine that by doing SELECT
> COUNT(*) FROM TABLE WHERE DURATION IS NULL, but once you get into the
> historical perspective (where the nulls are all real duration values), you
> have to figure our which duration values overlap with other duration
> values.

> ID_KEY DATETIME (nearest minute) DURATION
The basic query that provides the data you seek is:
select t1.ID_KEY, t1.DATETIME as STARTDT,
DATEADD(mi, t2.DURATION, t1.DATETIME) as ENDDT,
t2.DURATION
from mytable as t1
left outer join mytable as t2
on t1.ID_KEY = t2.ID_KEY
and t1.DATETIME is null
and t2.DATETIME is not null
order by ?
Using the above as a derived table, the logic you need is something along
the lines of:
declare @.target datetime
set @.target = '20060227 13:45:00.000'
select ....
from [this is where the derived table goes, assume an alias of durdata]
where STARTDT <= @.target
and coalesce (ENDDT, @.target) >= @.target
order by ?
This gives you information as of a particular moment in time. You should be
able to expand that logic to get information for a particular time period.

> Yeah, I know my full-minute rounding will screw up the analysis, but
> coming
> close would be nice right now. For example, the 153 second task was
> simultaneous with the two tasks that started one minute later. But how
> do
> you run some kind of query against the table for periods of time where the
> durations are all now complete (no nulls for yesterday, for example,
> because
> those tasks are complete). How do I determine those "max simultaneous
> tasks
> were in progress" during hour by hour windows of time? Or something like
> that? I really need this to determine staffing, because if we had 100
> simulatenous tasks between 8 and 8:10 AM yesterday morning, I know we need
> to hire more people.
If you want hour-by-hour information, just create (and populate) a
"calendar" table. This can be done in different ways - one way is
dynamically with a table-valued function. With that table, you join to the
derived table and substitute the variable boundary values with the
associated columns from the calendar table.
|||"Scott Morris" <bogus@.bogus.com> wrote in message
news:%23SUSI38OGHA.2124@.TK2MSFTNGP14.phx.gbl...[vbcol=seagreen]
when[vbcol=seagreen]
in
> I assume you realize why this task is so difficult. For those who don't,
> this is what happens when the schema is not properly normalized. In this
> case, I am assuming that there is a 1-1 relationship between the "start"
row[vbcol=seagreen]
> of a given task and the "end" row of a given task - both are related by a
> common value for ID_KEY. Comments below are predicated on these
> assumptions.
you
>
> The basic query that provides the data you seek is:
> select t1.ID_KEY, t1.DATETIME as STARTDT,
> DATEADD(mi, t2.DURATION, t1.DATETIME) as ENDDT,
> t2.DURATION
> from mytable as t1
> left outer join mytable as t2
> on t1.ID_KEY = t2.ID_KEY
> and t1.DATETIME is null
> and t2.DATETIME is not null
> order by ?
> Using the above as a derived table, the logic you need is something along
> the lines of:
> declare @.target datetime
> set @.target = '20060227 13:45:00.000'
> select ....
> from [this is where the derived table goes, assume an alias of durdata]
> where STARTDT <= @.target
> and coalesce (ENDDT, @.target) >= @.target
> order by ?
> This gives you information as of a particular moment in time. You should
be[vbcol=seagreen]
> able to expand that logic to get information for a particular time period.
the[vbcol=seagreen]
like[vbcol=seagreen]
need
> If you want hour-by-hour information, just create (and populate) a
> "calendar" table. This can be done in different ways - one way is
> dynamically with a table-valued function. With that table, you join to
the
> derived table and substitute the variable boundary values with the
> associated columns from the calendar table.
>
Thanks for the "join to itself" example. I'm not understanding the
calendar table, sorry. Are you able to give a quick example of that? Are
you meaning to create a temp table?
|||> Thanks for the "join to itself" example. I'm not understanding the
> calendar table, sorry. Are you able to give a quick example of that? Are
> you meaning to create a temp table?
Perhaps. There are many uses for a calendar table (or, more simply, a table
of sequential numbers). You can search the newsgroup for reasons and
examples of their usage. Whether there is value in making this information
permanent is something you must determine based on its useful as well as
other factors that may not be apparent to outsiders like us. Most people
discover that there are special ways of handling information based on
whether a date is a "work day" (as opposed to a holiday, snow day, or other
non-working day)
Assume a temp table contains this info. At its simplest, it is just a table
of dates. Simplying your request some more, lets assume that we want hourly
numbers for the current date. Given the previously posted queries, what
specifically do we need in order to generate the appropriate information?
Answer - we need the boundaries of our timeperiods. Back to the example, we
need a table of two columns that define our boundary values for each period
of interest. The rows would look like the following:
'20060227 00:00:00.000' , '20060227 01:00:00.000'
'20060227 01:00:00.000' , '20060227 02:00:00.000'
'20060227 02:00:00.000' , '20060227 03:00:00.000'
Did you notice the overlap of time from the end of one period to the start
of the next. By usage / convention, we'll prevent the overlap from altering
our numbers. Why overlap - for clarification / presentation purposes only.
To get your data, join this table using the previous derived table example -
replace the variable usage with the appropriate columns and add the group by
information. Focus particularly on the coalesce usage. Note that a task
applies to a period if the startdate of the task precedes the end date of
the period (not inclusive) and the end date of the task falls on/after the
start date of the period (inclusive - this is the "usage convention"
mentioned earlier). Note that a task that has not completed applies to all
periods that end after the task start date.
There are tricks to generating the timeperiod information. For now, it is
probably easiest to focus on the logic and ignore whatever tricks might be
used for generation. It probably makes most sense, from a developing
perspective, to create a temp table and populate it with insert statements
in a script. It's only 24 insert statements and you can copy/paste the
information quickly.
Play with the concept a bit. I'll work up an example if you still have
questions.
|||"Scott Morris" <bogus@.bogus.com> wrote in message
news:u1knRF%23OGHA.3728@.tk2msftngp13.phx.gbl...[vbcol=seagreen]
Are
> Perhaps. There are many uses for a calendar table (or, more simply, a
table
> of sequential numbers). You can search the newsgroup for reasons and
> examples of their usage. Whether there is value in making this
information
> permanent is something you must determine based on its useful as well as
> other factors that may not be apparent to outsiders like us. Most people
> discover that there are special ways of handling information based on
> whether a date is a "work day" (as opposed to a holiday, snow day, or
other
> non-working day)
> Assume a temp table contains this info. At its simplest, it is just a
table
> of dates. Simplying your request some more, lets assume that we want
hourly
> numbers for the current date. Given the previously posted queries, what
> specifically do we need in order to generate the appropriate information?
> Answer - we need the boundaries of our timeperiods. Back to the example,
we
> need a table of two columns that define our boundary values for each
period
> of interest. The rows would look like the following:
> '20060227 00:00:00.000' , '20060227 01:00:00.000'
> '20060227 01:00:00.000' , '20060227 02:00:00.000'
> '20060227 02:00:00.000' , '20060227 03:00:00.000'
> Did you notice the overlap of time from the end of one period to the start
> of the next. By usage / convention, we'll prevent the overlap from
altering
> our numbers. Why overlap - for clarification / presentation purposes
only.
> To get your data, join this table using the previous derived table
example -
> replace the variable usage with the appropriate columns and add the group
by
> information. Focus particularly on the coalesce usage. Note that a task
> applies to a period if the startdate of the task precedes the end date of
> the period (not inclusive) and the end date of the task falls on/after the
> start date of the period (inclusive - this is the "usage convention"
> mentioned earlier). Note that a task that has not completed applies to all
> periods that end after the task start date.
> There are tricks to generating the timeperiod information. For now, it is
> probably easiest to focus on the logic and ignore whatever tricks might be
> used for generation. It probably makes most sense, from a developing
> perspective, to create a temp table and populate it with insert statements
> in a script. It's only 24 insert statements and you can copy/paste the
> information quickly.
> Play with the concept a bit. I'll work up an example if you still have
> questions.
>
So you were talking about creating a truly separate table, with each row
being a period of time, like hourly. I understand now, thanks.
But one thing still escapes me. So you have the thousands of raw records
(the example records I gave in the beginning of this post) in each day. If
I said tell me the busiest time of day yesterday, and how many simultaneous
tasks were being executed at that moment, how would you determine the
answer? Would you create 24*60 rows in your calendar table, one for each
minute? And if so, how would you do this in an automated way, to both
create the calendar table rows AND insert the count value into each row? I
certainly don't want to hand-type 24*60 entries for each day. I can
imagine writing code that looks through a recordset, row by row, with
counters as it goes. But I would also think that there should be a way to
do this from query analyzer.
|||> So you were talking about creating a truly separate table, with each row
> being a period of time, like hourly. I understand now, thanks.
yes - based on your examples and questions only. Obviously, the solution
depends on what "answer" you seek.

> But one thing still escapes me. So you have the thousands of raw records
> (the example records I gave in the beginning of this post) in each day.
> If
> I said tell me the busiest time of day yesterday, and how many
> simultaneous
> tasks were being executed at that moment, how would you determine the
> answer? Would you create 24*60 rows in your calendar table, one for each
> minute?
Good requirements often lead you to a good solution. Define "busiest time
of the day". This raises the issue of how accurate an answer you seek (and
how accurate your data is). If the data is only accurate to the nearest
minute, then the answer is equally limited. Knowing that, we need to
calculate the outstanding task counts on a minute basis throughout the
period of interest (yesterday) and get the largest count. This involves 1
day x 24 hours x 60 minutes invidividual calculation periods; this then
drives the content of the temp table discussed earlier. BTW - a table of
1440 (24 x 60) rows is a very, VERY, small table.

> And if so, how would you do this in an automated way, to both
> create the calendar table rows AND insert the count value into each row?
> I
> certainly don't want to hand-type 24*60 entries for each day.
You said "automated", followed by "hand-type". Obviously, anything that you
do on a regular basis can be automated and there is no reason why you would
need to "hand-type" anything more than once. Is it possible to write a
script to populate a temp table with the hourly intervals for a specified
date? Of course. There is a looping construct in tsql. There are also
tricks, as mentioned earlier. Steve Kass has posted a UDF that generates a
table of sequential numbers in the .programming NG, if you want to see one
such technique.

> I can imagine writing code that looks through a recordset, row by row,
> with
> counters as it goes.
Yes - you do this because you are most familiar with conventional
programming. Good relational solutions involve set manipulations. Very
rarely is a "row-by-row" solution appropriate; often such a solution is far
from "best". Search the newsgroups for the term "cursor" to see the oft
repeated discussions about such things.

> But I would also think that there should be a way to do this from query
> analyzer.
tsql code is tsql code. How you execute it is your decision. QA is but one
tool that can do this.
|||> select t1.ID_KEY, t1.DATETIME as STARTDT,
> DATEADD(mi, t2.DURATION, t1.DATETIME) as ENDDT,
> t2.DURATION
> from mytable as t1
> left outer join mytable as t2
> on t1.ID_KEY = t2.ID_KEY
> and t1.DATETIME is null
> and t2.DATETIME is not null
> order by ?
This is wrong. Replace the datetime column in the join conditions with the
duration column. I should point out that there is an assumption regarding
the datetime column (nice name, btw) - specifically that all rows for a task
(identified by ID_KEY) have the same value for the DATETIME column.
|||A working example
set nocount on
go
if object_id('tempdb..#rawdata') is not null
drop table #rawdata
go
if object_id('tempdb..#period') is not null
drop table #period
go
create table #rawdata (
id_key int not null
, tstamp datetime not null
, duration int null
)
insert #rawdata (id_key, tstamp, duration)
select 31, '20060227 16:51:00', NULL
union all
select 31, '20060227 16:51:00', 181
union all
select 28, '20060227 08:03:00', null
union all
select 28, '20060227 08:03:00', 600
union all
select 12, '20060227 00:00:00', null
union all
select 900, '20060227 00:00:00', null
union all
select 901, '20060227 12:00:00', null
union all
select 88, '20060227 23:00:00', null
union all
select 88, '20060227 23:00:00', 60
select id_key, tstamp, duration from #rawdata order by id_key, tstamp,
duration
select t1.id_key, t1.tstamp as STARTDT,
dateadd (mi, t2.duration, t1.tstamp) as ENDDT,
t2.DURATION
from #rawdata as t1
left outer join #rawdata as t2
on t1.id_key = t2.id_key
and t1.duration is null
and t2.duration is not null
where t1.duration is null
create table #period (
pstart datetime not null
, pend datetime not null
)
declare @.temp int, @.start datetime
set @.start = '20060227'
while @.start < '20060228'
begin
insert #period (pstart, pend) values (@.start, dateadd (hour, 1, @.start))
set @.start = dateadd (hour, 1, @.start)
end
select * from #period order by pstart
select *
from (
select t1.id_key, t1.tstamp as startdt,
dateadd (mi, t2.duration, t1.tstamp) as enddt,
t2.duration
from #rawdata as t1
left outer join #rawdata as t2
on t1.id_key = t2.id_key
and t1.duration is null
and t2.duration is not null
where t1.duration is null
) as normal
select #period.*, normal.*
from (
select t1.id_key, t1.tstamp as startdt,
dateadd (mi, t2.duration, t1.tstamp) as enddt,
t2.duration
from #rawdata as t1
left outer join #rawdata as t2
on t1.id_key = t2.id_key
and t1.duration is null
and t2.duration is not null
where t1.duration is null
) as normal
inner join #period
on normal.startdt < #period.pend
and coalesce (normal.enddt, #period.pend) > #period.pstart
order by normal.id_key, #period.pstart
select #period.pstart, #period.pend, count(*)
from (
select t1.id_key, t1.tstamp as startdt,
dateadd (mi, t2.duration, t1.tstamp) as enddt,
t2.duration
from #rawdata as t1
left outer join #rawdata as t2
on t1.id_key = t2.id_key
and t1.duration is null
and t2.duration is not null
where t1.duration is null
) as normal
inner join #period
on normal.startdt < #period.pend
and coalesce (normal.enddt, #period.pend) > #period.pstart
group by #period.pstart, #period.pend
order by #period.pstart

How to do this SQL analysis...

With SQL 2005 Standard: I have records in a table that show how long it
takes to complete a task...
ID_KEY DATETIME (nearest minute) DURATION
When a task is started, a record is added with a "null" duration, and when
the task is finished, the duration is updated to represent the number of
seconds the task took to complete. So, here's sample values:
133541 2006-02-27 16:51:00 NULL
133540 2006-02-27 16:51:00 60
133539 2006-02-27 16:50:00 NULL
133538 2006-02-27 16:50:00 153
133537 2006-02-27 16:50:00 30
The above data shows that 2 tasks are not complete and 3 tasks finished in
those respective #seconds.
My question: I would like to know how to determine the number of
simulataneous tasks in process for any given period of time, or by the hour
of the day. Right this moment, I can determine that by doing SELECT
COUNT(*) FROM TABLE WHERE DURATION IS NULL, but once you get into the
historical perspective (where the nulls are all real duration values), you
have to figure our which duration values overlap with other duration values.
Yeah, I know my full-minute rounding will screw up the analysis, but coming
close would be nice right now. For example, the 153 second task was
simultaneous with the two tasks that started one minute later. But how do
you run some kind of query against the table for periods of time where the
durations are all now complete (no nulls for yesterday, for example, because
those tasks are complete). How do I determine those "max simultaneous tasks
were in progress" during hour by hour windows of time? Or something like
that? I really need this to determine staffing, because if we had 100
simulatenous tasks between 8 and 8:10 AM yesterday morning, I know we need
to hire more people."HK" <replywithingroup@.notreal.com> wrote in message
news:8kGMf.2874$xS5.921@.tornado.socal.rr.com...
> With SQL 2005 Standard: I have records in a table that show how long it
> takes to complete a task...
> ID_KEY DATETIME (nearest minute) DURATION
> When a task is started, a record is added with a "null" duration, and when
> the task is finished, the duration is updated to represent the number of
> seconds the task took to complete. So, here's sample values:
> 133541 2006-02-27 16:51:00 NULL
> 133540 2006-02-27 16:51:00 60
> 133539 2006-02-27 16:50:00 NULL
> 133538 2006-02-27 16:50:00 153
> 133537 2006-02-27 16:50:00 30
> The above data shows that 2 tasks are not complete and 3 tasks finished in
> those respective #seconds.
>
How about doing a DATEADD on the seconds for completed tasks as a time2 in
the query, then select BETWEEN time1 and time2.
Rick Sawtell
MCT, MCSD, MCDBA|||"Rick Sawtell" <Quickening@.msn.com> wrote in message
news:%23BssXF8OGHA.3728@.tk2msftngp13.phx.gbl...
> "HK" <replywithingroup@.notreal.com> wrote in message
> news:8kGMf.2874$xS5.921@.tornado.socal.rr.com...
when[vbcol=seagreen]
in[vbcol=seagreen]
> How about doing a DATEADD on the seconds for completed tasks as a time2 in
> the query, then select BETWEEN time1 and time2.
> Rick Sawtell
> MCT, MCSD, MCDBA
>
>
>
Although I understand the concept and how to use date functions, I still
don't know how to put this into production in a real query (the selecting
count between time1 and time2 is still not clear when I try), and also how
to group by time intervals. Sample syntax would be much appreciated.
Thanks.|||> When a task is started, a record is added with a "null" duration, and when
> the task is finished, the duration is updated to represent the number of
> seconds the task took to complete. So, here's sample values:
> 133541 2006-02-27 16:51:00 NULL
> 133540 2006-02-27 16:51:00 60
> 133539 2006-02-27 16:50:00 NULL
> 133538 2006-02-27 16:50:00 153
> 133537 2006-02-27 16:50:00 30
> The above data shows that 2 tasks are not complete and 3 tasks finished in
> those respective #seconds.
I assume you realize why this task is so difficult. For those who don't,
this is what happens when the schema is not properly normalized. In this
case, I am assuming that there is a 1-1 relationship between the "start" row
of a given task and the "end" row of a given task - both are related by a
common value for ID_KEY. Comments below are predicated on these
assumptions.

> My question: I would like to know how to determine the number of
> simulataneous tasks in process for any given period of time, or by the
> hour
> of the day. Right this moment, I can determine that by doing SELECT
> COUNT(*) FROM TABLE WHERE DURATION IS NULL, but once you get into the
> historical perspective (where the nulls are all real duration values), you
> have to figure our which duration values overlap with other duration
> values.

> ID_KEY DATETIME (nearest minute) DURATION
The basic query that provides the data you seek is:
select t1.ID_KEY, t1.DATETIME as STARTDT,
DATEADD(mi, t2.DURATION, t1.DATETIME) as ENDDT,
t2.DURATION
from mytable as t1
left outer join mytable as t2
on t1.ID_KEY = t2.ID_KEY
and t1.DATETIME is null
and t2.DATETIME is not null
order by '
Using the above as a derived table, the logic you need is something along
the lines of:
declare @.target datetime
set @.target = '20060227 13:45:00.000'
select ....
from [this is where the derived table goes, assume an alias of durdata]
where STARTDT <= @.target
and coalesce (ENDDT, @.target) >= @.target
order by '
This gives you information as of a particular moment in time. You should be
able to expand that logic to get information for a particular time period.

> Yeah, I know my full-minute rounding will screw up the analysis, but
> coming
> close would be nice right now. For example, the 153 second task was
> simultaneous with the two tasks that started one minute later. But how
> do
> you run some kind of query against the table for periods of time where the
> durations are all now complete (no nulls for yesterday, for example,
> because
> those tasks are complete). How do I determine those "max simultaneous
> tasks
> were in progress" during hour by hour windows of time? Or something like
> that? I really need this to determine staffing, because if we had 100
> simulatenous tasks between 8 and 8:10 AM yesterday morning, I know we need
> to hire more people.
If you want hour-by-hour information, just create (and populate) a
"calendar" table. This can be done in different ways - one way is
dynamically with a table-valued function. With that table, you join to the
derived table and substitute the variable boundary values with the
associated columns from the calendar table.|||"Scott Morris" <bogus@.bogus.com> wrote in message
news:%23SUSI38OGHA.2124@.TK2MSFTNGP14.phx.gbl...
when[vbcol=seagreen]
in[vbcol=seagreen]
> I assume you realize why this task is so difficult. For those who don't,
> this is what happens when the schema is not properly normalized. In this
> case, I am assuming that there is a 1-1 relationship between the "start"
row
> of a given task and the "end" row of a given task - both are related by a
> common value for ID_KEY. Comments below are predicated on these
> assumptions.
>
you[vbcol=seagreen]
>
> The basic query that provides the data you seek is:
> select t1.ID_KEY, t1.DATETIME as STARTDT,
> DATEADD(mi, t2.DURATION, t1.DATETIME) as ENDDT,
> t2.DURATION
> from mytable as t1
> left outer join mytable as t2
> on t1.ID_KEY = t2.ID_KEY
> and t1.DATETIME is null
> and t2.DATETIME is not null
> order by '
> Using the above as a derived table, the logic you need is something along
> the lines of:
> declare @.target datetime
> set @.target = '20060227 13:45:00.000'
> select ....
> from [this is where the derived table goes, assume an alias of durdata
]
> where STARTDT <= @.target
> and coalesce (ENDDT, @.target) >= @.target
> order by '
> This gives you information as of a particular moment in time. You should
be
> able to expand that logic to get information for a particular time period.
>
the[vbcol=seagreen]
like[vbcol=seagreen]
need[vbcol=seagreen]
> If you want hour-by-hour information, just create (and populate) a
> "calendar" table. This can be done in different ways - one way is
> dynamically with a table-valued function. With that table, you join to
the
> derived table and substitute the variable boundary values with the
> associated columns from the calendar table.
>
Thanks for the "join to itself" example. I'm not understanding the
calendar table, sorry. Are you able to give a quick example of that? Are
you meaning to create a temp table?|||> Thanks for the "join to itself" example. I'm not understanding the
> calendar table, sorry. Are you able to give a quick example of that? Are
> you meaning to create a temp table?
Perhaps. There are many uses for a calendar table (or, more simply, a table
of sequential numbers). You can search the newsgroup for reasons and
examples of their usage. Whether there is value in making this information
permanent is something you must determine based on its useful as well as
other factors that may not be apparent to outsiders like us. Most people
discover that there are special ways of handling information based on
whether a date is a "work day" (as opposed to a holiday, snow day, or other
non-working day)
Assume a temp table contains this info. At its simplest, it is just a table
of dates. Simplying your request some more, lets assume that we want hourly
numbers for the current date. Given the previously posted queries, what
specifically do we need in order to generate the appropriate information?
Answer - we need the boundaries of our timeperiods. Back to the example, we
need a table of two columns that define our boundary values for each period
of interest. The rows would look like the following:
'20060227 00:00:00.000' , '20060227 01:00:00.000'
'20060227 01:00:00.000' , '20060227 02:00:00.000'
'20060227 02:00:00.000' , '20060227 03:00:00.000'
Did you notice the overlap of time from the end of one period to the start
of the next. By usage / convention, we'll prevent the overlap from altering
our numbers. Why overlap - for clarification / presentation purposes only.
To get your data, join this table using the previous derived table example -
replace the variable usage with the appropriate columns and add the group by
information. Focus particularly on the coalesce usage. Note that a task
applies to a period if the startdate of the task precedes the end date of
the period (not inclusive) and the end date of the task falls on/after the
start date of the period (inclusive - this is the "usage convention"
mentioned earlier). Note that a task that has not completed applies to all
periods that end after the task start date.
There are tricks to generating the timeperiod information. For now, it is
probably easiest to focus on the logic and ignore whatever tricks might be
used for generation. It probably makes most sense, from a developing
perspective, to create a temp table and populate it with insert statements
in a script. It's only 24 insert statements and you can copy/paste the
information quickly.
Play with the concept a bit. I'll work up an example if you still have
questions.|||"Scott Morris" <bogus@.bogus.com> wrote in message
news:u1knRF%23OGHA.3728@.tk2msftngp13.phx.gbl...
Are[vbcol=seagreen]
> Perhaps. There are many uses for a calendar table (or, more simply, a
table
> of sequential numbers). You can search the newsgroup for reasons and
> examples of their usage. Whether there is value in making this
information
> permanent is something you must determine based on its useful as well as
> other factors that may not be apparent to outsiders like us. Most people
> discover that there are special ways of handling information based on
> whether a date is a "work day" (as opposed to a holiday, snow day, or
other
> non-working day)
> Assume a temp table contains this info. At its simplest, it is just a
table
> of dates. Simplying your request some more, lets assume that we want
hourly
> numbers for the current date. Given the previously posted queries, what
> specifically do we need in order to generate the appropriate information?
> Answer - we need the boundaries of our timeperiods. Back to the example,
we
> need a table of two columns that define our boundary values for each
period
> of interest. The rows would look like the following:
> '20060227 00:00:00.000' , '20060227 01:00:00.000'
> '20060227 01:00:00.000' , '20060227 02:00:00.000'
> '20060227 02:00:00.000' , '20060227 03:00:00.000'
> Did you notice the overlap of time from the end of one period to the start
> of the next. By usage / convention, we'll prevent the overlap from
altering
> our numbers. Why overlap - for clarification / presentation purposes
only.
> To get your data, join this table using the previous derived table
example -
> replace the variable usage with the appropriate columns and add the group
by
> information. Focus particularly on the coalesce usage. Note that a task
> applies to a period if the startdate of the task precedes the end date of
> the period (not inclusive) and the end date of the task falls on/after the
> start date of the period (inclusive - this is the "usage convention"
> mentioned earlier). Note that a task that has not completed applies to all
> periods that end after the task start date.
> There are tricks to generating the timeperiod information. For now, it is
> probably easiest to focus on the logic and ignore whatever tricks might be
> used for generation. It probably makes most sense, from a developing
> perspective, to create a temp table and populate it with insert statements
> in a script. It's only 24 insert statements and you can copy/paste the
> information quickly.
> Play with the concept a bit. I'll work up an example if you still have
> questions.
>
So you were talking about creating a truly separate table, with each row
being a period of time, like hourly. I understand now, thanks.
But one thing still escapes me. So you have the thousands of raw records
(the example records I gave in the beginning of this post) in each day. If
I said tell me the busiest time of day yesterday, and how many simultaneous
tasks were being executed at that moment, how would you determine the
answer? Would you create 24*60 rows in your calendar table, one for each
minute? And if so, how would you do this in an automated way, to both
create the calendar table rows AND insert the count value into each row? I
certainly don't want to hand-type 24*60 entries for each day. I can
imagine writing code that looks through a recordset, row by row, with
counters as it goes. But I would also think that there should be a way to
do this from query analyzer.|||> So you were talking about creating a truly separate table, with each row
> being a period of time, like hourly. I understand now, thanks.
yes - based on your examples and questions only. Obviously, the solution
depends on what "answer" you seek.

> But one thing still escapes me. So you have the thousands of raw records
> (the example records I gave in the beginning of this post) in each day.
> If
> I said tell me the busiest time of day yesterday, and how many
> simultaneous
> tasks were being executed at that moment, how would you determine the
> answer? Would you create 24*60 rows in your calendar table, one for each
> minute?
Good requirements often lead you to a good solution. Define "busiest time
of the day". This raises the issue of how accurate an answer you seek (and
how accurate your data is). If the data is only accurate to the nearest
minute, then the answer is equally limited. Knowing that, we need to
calculate the outstanding task counts on a minute basis throughout the
period of interest (yesterday) and get the largest count. This involves 1
day x 24 hours x 60 minutes invidividual calculation periods; this then
drives the content of the temp table discussed earlier. BTW - a table of
1440 (24 x 60) rows is a very, VERY, small table.

> And if so, how would you do this in an automated way, to both
> create the calendar table rows AND insert the count value into each row?
> I
> certainly don't want to hand-type 24*60 entries for each day.
You said "automated", followed by "hand-type". Obviously, anything that you
do on a regular basis can be automated and there is no reason why you would
need to "hand-type" anything more than once. Is it possible to write a
script to populate a temp table with the hourly intervals for a specified
date? Of course. There is a looping construct in tsql. There are also
tricks, as mentioned earlier. Steve Kass has posted a UDF that generates a
table of sequential numbers in the .programming NG, if you want to see one
such technique.

> I can imagine writing code that looks through a recordset, row by row,
> with
> counters as it goes.
Yes - you do this because you are most familiar with conventional
programming. Good relational solutions involve set manipulations. Very
rarely is a "row-by-row" solution appropriate; often such a solution is far
from "best". Search the newsgroups for the term "cursor" to see the oft
repeated discussions about such things.

> But I would also think that there should be a way to do this from query
> analyzer.
tsql code is tsql code. How you execute it is your decision. QA is but one
tool that can do this.|||> select t1.ID_KEY, t1.DATETIME as STARTDT,
> DATEADD(mi, t2.DURATION, t1.DATETIME) as ENDDT,
> t2.DURATION
> from mytable as t1
> left outer join mytable as t2
> on t1.ID_KEY = t2.ID_KEY
> and t1.DATETIME is null
> and t2.DATETIME is not null
> order by '
This is wrong. Replace the datetime column in the join conditions with the
duration column. I should point out that there is an assumption regarding
the datetime column (nice name, btw) - specifically that all rows for a task
(identified by ID_KEY) have the same value for the DATETIME column.|||A working example
set nocount on
go
if object_id('tempdb..#rawdata') is not null
drop table #rawdata
go
if object_id('tempdb..#period') is not null
drop table #period
go
create table #rawdata (
id_key int not null
, tstamp datetime not null
, duration int null
)
insert #rawdata (id_key, tstamp, duration)
select 31, '20060227 16:51:00', NULL
union all
select 31, '20060227 16:51:00', 181
union all
select 28, '20060227 08:03:00', null
union all
select 28, '20060227 08:03:00', 600
union all
select 12, '20060227 00:00:00', null
union all
select 900, '20060227 00:00:00', null
union all
select 901, '20060227 12:00:00', null
union all
select 88, '20060227 23:00:00', null
union all
select 88, '20060227 23:00:00', 60
select id_key, tstamp, duration from #rawdata order by id_key, tstamp,
duration
select t1.id_key, t1.tstamp as STARTDT,
dateadd (mi, t2.duration, t1.tstamp) as ENDDT,
t2.DURATION
from #rawdata as t1
left outer join #rawdata as t2
on t1.id_key = t2.id_key
and t1.duration is null
and t2.duration is not null
where t1.duration is null
create table #period (
pstart datetime not null
, pend datetime not null
)
declare @.temp int, @.start datetime
set @.start = '20060227'
while @.start < '20060228'
begin
insert #period (pstart, pend) values (@.start, dateadd (hour, 1, @.start))
set @.start = dateadd (hour, 1, @.start)
end
select * from #period order by pstart
select *
from (
select t1.id_key, t1.tstamp as startdt,
dateadd (mi, t2.duration, t1.tstamp) as enddt,
t2.duration
from #rawdata as t1
left outer join #rawdata as t2
on t1.id_key = t2.id_key
and t1.duration is null
and t2.duration is not null
where t1.duration is null
) as normal
select #period.*, normal.*
from (
select t1.id_key, t1.tstamp as startdt,
dateadd (mi, t2.duration, t1.tstamp) as enddt,
t2.duration
from #rawdata as t1
left outer join #rawdata as t2
on t1.id_key = t2.id_key
and t1.duration is null
and t2.duration is not null
where t1.duration is null
) as normal
inner join #period
on normal.startdt < #period.pend
and coalesce (normal.enddt, #period.pend) > #period.pstart
order by normal.id_key, #period.pstart
select #period.pstart, #period.pend, count(*)
from (
select t1.id_key, t1.tstamp as startdt,
dateadd (mi, t2.duration, t1.tstamp) as enddt,
t2.duration
from #rawdata as t1
left outer join #rawdata as t2
on t1.id_key = t2.id_key
and t1.duration is null
and t2.duration is not null
where t1.duration is null
) as normal
inner join #period
on normal.startdt < #period.pend
and coalesce (normal.enddt, #period.pend) > #period.pstart
group by #period.pstart, #period.pend
order by #period.pstart

How to do this SQL analysis...

With SQL 2005 Standard: I have records in a table that show how long it
takes to complete a task...
ID_KEY DATETIME (nearest minute) DURATION
When a task is started, a record is added with a "null" duration, and when
the task is finished, the duration is updated to represent the number of
seconds the task took to complete. So, here's sample values:
133541 2006-02-27 16:51:00 NULL
133540 2006-02-27 16:51:00 60
133539 2006-02-27 16:50:00 NULL
133538 2006-02-27 16:50:00 153
133537 2006-02-27 16:50:00 30
The above data shows that 2 tasks are not complete and 3 tasks finished in
those respective #seconds.
My question: I would like to know how to determine the number of
simulataneous tasks in process for any given period of time, or by the hour
of the day. Right this moment, I can determine that by doing SELECT
COUNT(*) FROM TABLE WHERE DURATION IS NULL, but once you get into the
historical perspective (where the nulls are all real duration values), you
have to figure our which duration values overlap with other duration values.
Yeah, I know my full-minute rounding will screw up the analysis, but coming
close would be nice right now. For example, the 153 second task was
simultaneous with the two tasks that started one minute later. But how do
you run some kind of query against the table for periods of time where the
durations are all now complete (no nulls for yesterday, for example, because
those tasks are complete). How do I determine those "max simultaneous tasks
were in progress" during hour by hour windows of time? Or something like
that? I really need this to determine staffing, because if we had 100
simulatenous tasks between 8 and 8:10 AM yesterday morning, I know we need
to hire more people."HK" <replywithingroup@.notreal.com> wrote in message
news:8kGMf.2874$xS5.921@.tornado.socal.rr.com...
> With SQL 2005 Standard: I have records in a table that show how long it
> takes to complete a task...
> ID_KEY DATETIME (nearest minute) DURATION
> When a task is started, a record is added with a "null" duration, and when
> the task is finished, the duration is updated to represent the number of
> seconds the task took to complete. So, here's sample values:
> 133541 2006-02-27 16:51:00 NULL
> 133540 2006-02-27 16:51:00 60
> 133539 2006-02-27 16:50:00 NULL
> 133538 2006-02-27 16:50:00 153
> 133537 2006-02-27 16:50:00 30
> The above data shows that 2 tasks are not complete and 3 tasks finished in
> those respective #seconds.
>
How about doing a DATEADD on the seconds for completed tasks as a time2 in
the query, then select BETWEEN time1 and time2.
Rick Sawtell
MCT, MCSD, MCDBA|||"Rick Sawtell" <Quickening@.msn.com> wrote in message
news:%23BssXF8OGHA.3728@.tk2msftngp13.phx.gbl...
> "HK" <replywithingroup@.notreal.com> wrote in message
> news:8kGMf.2874$xS5.921@.tornado.socal.rr.com...
> > With SQL 2005 Standard: I have records in a table that show how long it
> > takes to complete a task...
> >
> > ID_KEY DATETIME (nearest minute) DURATION
> >
> > When a task is started, a record is added with a "null" duration, and
when
> > the task is finished, the duration is updated to represent the number of
> > seconds the task took to complete. So, here's sample values:
> >
> > 133541 2006-02-27 16:51:00 NULL
> > 133540 2006-02-27 16:51:00 60
> > 133539 2006-02-27 16:50:00 NULL
> > 133538 2006-02-27 16:50:00 153
> > 133537 2006-02-27 16:50:00 30
> >
> > The above data shows that 2 tasks are not complete and 3 tasks finished
in
> > those respective #seconds.
> >
> How about doing a DATEADD on the seconds for completed tasks as a time2 in
> the query, then select BETWEEN time1 and time2.
> Rick Sawtell
> MCT, MCSD, MCDBA
>
>
>
Although I understand the concept and how to use date functions, I still
don't know how to put this into production in a real query (the selecting
count between time1 and time2 is still not clear when I try), and also how
to group by time intervals. Sample syntax would be much appreciated.
Thanks.|||> When a task is started, a record is added with a "null" duration, and when
> the task is finished, the duration is updated to represent the number of
> seconds the task took to complete. So, here's sample values:
> 133541 2006-02-27 16:51:00 NULL
> 133540 2006-02-27 16:51:00 60
> 133539 2006-02-27 16:50:00 NULL
> 133538 2006-02-27 16:50:00 153
> 133537 2006-02-27 16:50:00 30
> The above data shows that 2 tasks are not complete and 3 tasks finished in
> those respective #seconds.
I assume you realize why this task is so difficult. For those who don't,
this is what happens when the schema is not properly normalized. In this
case, I am assuming that there is a 1-1 relationship between the "start" row
of a given task and the "end" row of a given task - both are related by a
common value for ID_KEY. Comments below are predicated on these
assumptions.
> My question: I would like to know how to determine the number of
> simulataneous tasks in process for any given period of time, or by the
> hour
> of the day. Right this moment, I can determine that by doing SELECT
> COUNT(*) FROM TABLE WHERE DURATION IS NULL, but once you get into the
> historical perspective (where the nulls are all real duration values), you
> have to figure our which duration values overlap with other duration
> values.
> ID_KEY DATETIME (nearest minute) DURATION
The basic query that provides the data you seek is:
select t1.ID_KEY, t1.DATETIME as STARTDT,
DATEADD(mi, t2.DURATION, t1.DATETIME) as ENDDT,
t2.DURATION
from mytable as t1
left outer join mytable as t2
on t1.ID_KEY = t2.ID_KEY
and t1.DATETIME is null
and t2.DATETIME is not null
order by '
Using the above as a derived table, the logic you need is something along
the lines of:
declare @.target datetime
set @.target = '20060227 13:45:00.000'
select ....
from [this is where the derived table goes, assume an alias of durdata]
where STARTDT <= @.target
and coalesce (ENDDT, @.target) >= @.target
order by '
This gives you information as of a particular moment in time. You should be
able to expand that logic to get information for a particular time period.
> Yeah, I know my full-minute rounding will screw up the analysis, but
> coming
> close would be nice right now. For example, the 153 second task was
> simultaneous with the two tasks that started one minute later. But how
> do
> you run some kind of query against the table for periods of time where the
> durations are all now complete (no nulls for yesterday, for example,
> because
> those tasks are complete). How do I determine those "max simultaneous
> tasks
> were in progress" during hour by hour windows of time? Or something like
> that? I really need this to determine staffing, because if we had 100
> simulatenous tasks between 8 and 8:10 AM yesterday morning, I know we need
> to hire more people.
If you want hour-by-hour information, just create (and populate) a
"calendar" table. This can be done in different ways - one way is
dynamically with a table-valued function. With that table, you join to the
derived table and substitute the variable boundary values with the
associated columns from the calendar table.|||"Scott Morris" <bogus@.bogus.com> wrote in message
news:%23SUSI38OGHA.2124@.TK2MSFTNGP14.phx.gbl...
> > When a task is started, a record is added with a "null" duration, and
when
> > the task is finished, the duration is updated to represent the number of
> > seconds the task took to complete. So, here's sample values:
> >
> > 133541 2006-02-27 16:51:00 NULL
> > 133540 2006-02-27 16:51:00 60
> > 133539 2006-02-27 16:50:00 NULL
> > 133538 2006-02-27 16:50:00 153
> > 133537 2006-02-27 16:50:00 30
> >
> > The above data shows that 2 tasks are not complete and 3 tasks finished
in
> > those respective #seconds.
> I assume you realize why this task is so difficult. For those who don't,
> this is what happens when the schema is not properly normalized. In this
> case, I am assuming that there is a 1-1 relationship between the "start"
row
> of a given task and the "end" row of a given task - both are related by a
> common value for ID_KEY. Comments below are predicated on these
> assumptions.
> > My question: I would like to know how to determine the number of
> > simulataneous tasks in process for any given period of time, or by the
> > hour
> > of the day. Right this moment, I can determine that by doing SELECT
> > COUNT(*) FROM TABLE WHERE DURATION IS NULL, but once you get into the
> > historical perspective (where the nulls are all real duration values),
you
> > have to figure our which duration values overlap with other duration
> > values.
> > ID_KEY DATETIME (nearest minute) DURATION
> The basic query that provides the data you seek is:
> select t1.ID_KEY, t1.DATETIME as STARTDT,
> DATEADD(mi, t2.DURATION, t1.DATETIME) as ENDDT,
> t2.DURATION
> from mytable as t1
> left outer join mytable as t2
> on t1.ID_KEY = t2.ID_KEY
> and t1.DATETIME is null
> and t2.DATETIME is not null
> order by '
> Using the above as a derived table, the logic you need is something along
> the lines of:
> declare @.target datetime
> set @.target = '20060227 13:45:00.000'
> select ....
> from [this is where the derived table goes, assume an alias of durdata]
> where STARTDT <= @.target
> and coalesce (ENDDT, @.target) >= @.target
> order by '
> This gives you information as of a particular moment in time. You should
be
> able to expand that logic to get information for a particular time period.
> > Yeah, I know my full-minute rounding will screw up the analysis, but
> > coming
> > close would be nice right now. For example, the 153 second task was
> > simultaneous with the two tasks that started one minute later. But how
> > do
> > you run some kind of query against the table for periods of time where
the
> > durations are all now complete (no nulls for yesterday, for example,
> > because
> > those tasks are complete). How do I determine those "max simultaneous
> > tasks
> > were in progress" during hour by hour windows of time? Or something
like
> > that? I really need this to determine staffing, because if we had 100
> > simulatenous tasks between 8 and 8:10 AM yesterday morning, I know we
need
> > to hire more people.
> If you want hour-by-hour information, just create (and populate) a
> "calendar" table. This can be done in different ways - one way is
> dynamically with a table-valued function. With that table, you join to
the
> derived table and substitute the variable boundary values with the
> associated columns from the calendar table.
>
Thanks for the "join to itself" example. I'm not understanding the
calendar table, sorry. Are you able to give a quick example of that? Are
you meaning to create a temp table?|||> Thanks for the "join to itself" example. I'm not understanding the
> calendar table, sorry. Are you able to give a quick example of that? Are
> you meaning to create a temp table?
Perhaps. There are many uses for a calendar table (or, more simply, a table
of sequential numbers). You can search the newsgroup for reasons and
examples of their usage. Whether there is value in making this information
permanent is something you must determine based on its useful as well as
other factors that may not be apparent to outsiders like us. Most people
discover that there are special ways of handling information based on
whether a date is a "work day" (as opposed to a holiday, snow day, or other
non-working day)
Assume a temp table contains this info. At its simplest, it is just a table
of dates. Simplying your request some more, lets assume that we want hourly
numbers for the current date. Given the previously posted queries, what
specifically do we need in order to generate the appropriate information?
Answer - we need the boundaries of our timeperiods. Back to the example, we
need a table of two columns that define our boundary values for each period
of interest. The rows would look like the following:
'20060227 00:00:00.000' , '20060227 01:00:00.000'
'20060227 01:00:00.000' , '20060227 02:00:00.000'
'20060227 02:00:00.000' , '20060227 03:00:00.000'
Did you notice the overlap of time from the end of one period to the start
of the next. By usage / convention, we'll prevent the overlap from altering
our numbers. Why overlap - for clarification / presentation purposes only.
To get your data, join this table using the previous derived table example -
replace the variable usage with the appropriate columns and add the group by
information. Focus particularly on the coalesce usage. Note that a task
applies to a period if the startdate of the task precedes the end date of
the period (not inclusive) and the end date of the task falls on/after the
start date of the period (inclusive - this is the "usage convention"
mentioned earlier). Note that a task that has not completed applies to all
periods that end after the task start date.
There are tricks to generating the timeperiod information. For now, it is
probably easiest to focus on the logic and ignore whatever tricks might be
used for generation. It probably makes most sense, from a developing
perspective, to create a temp table and populate it with insert statements
in a script. It's only 24 insert statements and you can copy/paste the
information quickly.
Play with the concept a bit. I'll work up an example if you still have
questions.|||"Scott Morris" <bogus@.bogus.com> wrote in message
news:u1knRF%23OGHA.3728@.tk2msftngp13.phx.gbl...
> > Thanks for the "join to itself" example. I'm not understanding the
> > calendar table, sorry. Are you able to give a quick example of that?
Are
> > you meaning to create a temp table?
> Perhaps. There are many uses for a calendar table (or, more simply, a
table
> of sequential numbers). You can search the newsgroup for reasons and
> examples of their usage. Whether there is value in making this
information
> permanent is something you must determine based on its useful as well as
> other factors that may not be apparent to outsiders like us. Most people
> discover that there are special ways of handling information based on
> whether a date is a "work day" (as opposed to a holiday, snow day, or
other
> non-working day)
> Assume a temp table contains this info. At its simplest, it is just a
table
> of dates. Simplying your request some more, lets assume that we want
hourly
> numbers for the current date. Given the previously posted queries, what
> specifically do we need in order to generate the appropriate information?
> Answer - we need the boundaries of our timeperiods. Back to the example,
we
> need a table of two columns that define our boundary values for each
period
> of interest. The rows would look like the following:
> '20060227 00:00:00.000' , '20060227 01:00:00.000'
> '20060227 01:00:00.000' , '20060227 02:00:00.000'
> '20060227 02:00:00.000' , '20060227 03:00:00.000'
> Did you notice the overlap of time from the end of one period to the start
> of the next. By usage / convention, we'll prevent the overlap from
altering
> our numbers. Why overlap - for clarification / presentation purposes
only.
> To get your data, join this table using the previous derived table
example -
> replace the variable usage with the appropriate columns and add the group
by
> information. Focus particularly on the coalesce usage. Note that a task
> applies to a period if the startdate of the task precedes the end date of
> the period (not inclusive) and the end date of the task falls on/after the
> start date of the period (inclusive - this is the "usage convention"
> mentioned earlier). Note that a task that has not completed applies to all
> periods that end after the task start date.
> There are tricks to generating the timeperiod information. For now, it is
> probably easiest to focus on the logic and ignore whatever tricks might be
> used for generation. It probably makes most sense, from a developing
> perspective, to create a temp table and populate it with insert statements
> in a script. It's only 24 insert statements and you can copy/paste the
> information quickly.
> Play with the concept a bit. I'll work up an example if you still have
> questions.
>
So you were talking about creating a truly separate table, with each row
being a period of time, like hourly. I understand now, thanks.
But one thing still escapes me. So you have the thousands of raw records
(the example records I gave in the beginning of this post) in each day. If
I said tell me the busiest time of day yesterday, and how many simultaneous
tasks were being executed at that moment, how would you determine the
answer? Would you create 24*60 rows in your calendar table, one for each
minute? And if so, how would you do this in an automated way, to both
create the calendar table rows AND insert the count value into each row? I
certainly don't want to hand-type 24*60 entries for each day. I can
imagine writing code that looks through a recordset, row by row, with
counters as it goes. But I would also think that there should be a way to
do this from query analyzer.|||> So you were talking about creating a truly separate table, with each row
> being a period of time, like hourly. I understand now, thanks.
yes - based on your examples and questions only. Obviously, the solution
depends on what "answer" you seek.
> But one thing still escapes me. So you have the thousands of raw records
> (the example records I gave in the beginning of this post) in each day.
> If
> I said tell me the busiest time of day yesterday, and how many
> simultaneous
> tasks were being executed at that moment, how would you determine the
> answer? Would you create 24*60 rows in your calendar table, one for each
> minute?
Good requirements often lead you to a good solution. Define "busiest time
of the day". This raises the issue of how accurate an answer you seek (and
how accurate your data is). If the data is only accurate to the nearest
minute, then the answer is equally limited. Knowing that, we need to
calculate the outstanding task counts on a minute basis throughout the
period of interest (yesterday) and get the largest count. This involves 1
day x 24 hours x 60 minutes invidividual calculation periods; this then
drives the content of the temp table discussed earlier. BTW - a table of
1440 (24 x 60) rows is a very, VERY, small table.
> And if so, how would you do this in an automated way, to both
> create the calendar table rows AND insert the count value into each row?
> I
> certainly don't want to hand-type 24*60 entries for each day.
You said "automated", followed by "hand-type". Obviously, anything that you
do on a regular basis can be automated and there is no reason why you would
need to "hand-type" anything more than once. Is it possible to write a
script to populate a temp table with the hourly intervals for a specified
date? Of course. There is a looping construct in tsql. There are also
tricks, as mentioned earlier. Steve Kass has posted a UDF that generates a
table of sequential numbers in the .programming NG, if you want to see one
such technique.
> I can imagine writing code that looks through a recordset, row by row,
> with
> counters as it goes.
Yes - you do this because you are most familiar with conventional
programming. Good relational solutions involve set manipulations. Very
rarely is a "row-by-row" solution appropriate; often such a solution is far
from "best". Search the newsgroups for the term "cursor" to see the oft
repeated discussions about such things.
> But I would also think that there should be a way to do this from query
> analyzer.
tsql code is tsql code. How you execute it is your decision. QA is but one
tool that can do this.|||> select t1.ID_KEY, t1.DATETIME as STARTDT,
> DATEADD(mi, t2.DURATION, t1.DATETIME) as ENDDT,
> t2.DURATION
> from mytable as t1
> left outer join mytable as t2
> on t1.ID_KEY = t2.ID_KEY
> and t1.DATETIME is null
> and t2.DATETIME is not null
> order by '
This is wrong. Replace the datetime column in the join conditions with the
duration column. I should point out that there is an assumption regarding
the datetime column (nice name, btw) - specifically that all rows for a task
(identified by ID_KEY) have the same value for the DATETIME column.|||A working example
set nocount on
go
if object_id('tempdb..#rawdata') is not null
drop table #rawdata
go
if object_id('tempdb..#period') is not null
drop table #period
go
create table #rawdata (
id_key int not null
, tstamp datetime not null
, duration int null
)
insert #rawdata (id_key, tstamp, duration)
select 31, '20060227 16:51:00', NULL
union all
select 31, '20060227 16:51:00', 181
union all
select 28, '20060227 08:03:00', null
union all
select 28, '20060227 08:03:00', 600
union all
select 12, '20060227 00:00:00', null
union all
select 900, '20060227 00:00:00', null
union all
select 901, '20060227 12:00:00', null
union all
select 88, '20060227 23:00:00', null
union all
select 88, '20060227 23:00:00', 60
select id_key, tstamp, duration from #rawdata order by id_key, tstamp,
duration
select t1.id_key, t1.tstamp as STARTDT,
dateadd (mi, t2.duration, t1.tstamp) as ENDDT,
t2.DURATION
from #rawdata as t1
left outer join #rawdata as t2
on t1.id_key = t2.id_key
and t1.duration is null
and t2.duration is not null
where t1.duration is null
create table #period (
pstart datetime not null
, pend datetime not null
)
declare @.temp int, @.start datetime
set @.start = '20060227'
while @.start < '20060228'
begin
insert #period (pstart, pend) values (@.start, dateadd (hour, 1, @.start))
set @.start = dateadd (hour, 1, @.start)
end
select * from #period order by pstart
select *
from (
select t1.id_key, t1.tstamp as startdt,
dateadd (mi, t2.duration, t1.tstamp) as enddt,
t2.duration
from #rawdata as t1
left outer join #rawdata as t2
on t1.id_key = t2.id_key
and t1.duration is null
and t2.duration is not null
where t1.duration is null
) as normal
select #period.*, normal.*
from (
select t1.id_key, t1.tstamp as startdt,
dateadd (mi, t2.duration, t1.tstamp) as enddt,
t2.duration
from #rawdata as t1
left outer join #rawdata as t2
on t1.id_key = t2.id_key
and t1.duration is null
and t2.duration is not null
where t1.duration is null
) as normal
inner join #period
on normal.startdt < #period.pend
and coalesce (normal.enddt, #period.pend) > #period.pstart
order by normal.id_key, #period.pstart
select #period.pstart, #period.pend, count(*)
from (
select t1.id_key, t1.tstamp as startdt,
dateadd (mi, t2.duration, t1.tstamp) as enddt,
t2.duration
from #rawdata as t1
left outer join #rawdata as t2
on t1.id_key = t2.id_key
and t1.duration is null
and t2.duration is not null
where t1.duration is null
) as normal
inner join #period
on normal.startdt < #period.pend
and coalesce (normal.enddt, #period.pend) > #period.pstart
group by #period.pstart, #period.pend
order by #period.pstart|||Thank you for spending the time on the examples.
"Scott Morris" <bogus@.bogus.com> wrote in message
news:OBIYqVHPGHA.140@.TK2MSFTNGP12.phx.gbl...
> A working example
> set nocount on
> go
> if object_id('tempdb..#rawdata') is not null
> drop table #rawdata
> go
> if object_id('tempdb..#period') is not null
> drop table #period
> go
>
> create table #rawdata (
> id_key int not null
> , tstamp datetime not null
> , duration int null
> )
>
> insert #rawdata (id_key, tstamp, duration)
> select 31, '20060227 16:51:00', NULL
> union all
> select 31, '20060227 16:51:00', 181
> union all
> select 28, '20060227 08:03:00', null
> union all
> select 28, '20060227 08:03:00', 600
> union all
> select 12, '20060227 00:00:00', null
> union all
> select 900, '20060227 00:00:00', null
> union all
> select 901, '20060227 12:00:00', null
> union all
> select 88, '20060227 23:00:00', null
> union all
> select 88, '20060227 23:00:00', 60
> select id_key, tstamp, duration from #rawdata order by id_key, tstamp,
> duration
> select t1.id_key, t1.tstamp as STARTDT,
> dateadd (mi, t2.duration, t1.tstamp) as ENDDT,
> t2.DURATION
> from #rawdata as t1
> left outer join #rawdata as t2
> on t1.id_key = t2.id_key
> and t1.duration is null
> and t2.duration is not null
> where t1.duration is null
> create table #period (
> pstart datetime not null
> , pend datetime not null
> )
> declare @.temp int, @.start datetime
> set @.start = '20060227'
> while @.start < '20060228'
> begin
> insert #period (pstart, pend) values (@.start, dateadd (hour, 1,
@.start))
> set @.start = dateadd (hour, 1, @.start)
> end
> select * from #period order by pstart
> select *
> from (
> select t1.id_key, t1.tstamp as startdt,
> dateadd (mi, t2.duration, t1.tstamp) as enddt,
> t2.duration
> from #rawdata as t1
> left outer join #rawdata as t2
> on t1.id_key = t2.id_key
> and t1.duration is null
> and t2.duration is not null
> where t1.duration is null
> ) as normal
> select #period.*, normal.*
> from (
> select t1.id_key, t1.tstamp as startdt,
> dateadd (mi, t2.duration, t1.tstamp) as enddt,
> t2.duration
> from #rawdata as t1
> left outer join #rawdata as t2
> on t1.id_key = t2.id_key
> and t1.duration is null
> and t2.duration is not null
> where t1.duration is null
> ) as normal
> inner join #period
> on normal.startdt < #period.pend
> and coalesce (normal.enddt, #period.pend) > #period.pstart
> order by normal.id_key, #period.pstart
>
> select #period.pstart, #period.pend, count(*)
> from (
> select t1.id_key, t1.tstamp as startdt,
> dateadd (mi, t2.duration, t1.tstamp) as enddt,
> t2.duration
> from #rawdata as t1
> left outer join #rawdata as t2
> on t1.id_key = t2.id_key
> and t1.duration is null
> and t2.duration is not null
> where t1.duration is null
> ) as normal
> inner join #period
> on normal.startdt < #period.pend
> and coalesce (normal.enddt, #period.pend) > #period.pstart
> group by #period.pstart, #period.pend
> order by #period.pstart
>

Friday, February 24, 2012

How To Do this

I created some DropDownList's Dynamically based on the records in the Products table of Northwind Database Ie
Dim StrConn As String = ConfigurationManager.ConnectionStrings("....").ConnectionString
Dim MyConn As New SqlConnection(StrConn)
Dim MyAdapter As SqlDataAdapter
Dim MyDataSet As DataSet
Dim MyComm As SqlCommand
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim StrSelect As String = "Select ProductId,ProductName From Products"
MyAdapter = New SqlDataAdapter(StrSelect, MyConn)
MyDataSet = New DataSet
MyAdapter.Fill(MyDataSet, "Products")

For Each Dr As DataRow In MyDataSet.Tables("Products").Rows
Dim Drp As New DropDownList
Drp.ID = "Drp" & Dr.Item(0)
Drp.DataSource = MyDataSet.Tables("Products")
Drp.DataTextField = "ProductName"
Drp.DataValueField = "ProductId"
Drp.DataBind()

PlcConterol.Controls.Add(Drp)
Next
End Sub
I tried doing the samething using the DataReader but it creates only one DropDown Ie

While MyReader.Read
Dim Drp as New DropDownList

Drp.Id="Drp"

Drp.DataSource=MyReader

Drp.DataTextField="ProductName"

Drp.DataValueField="ProductId"

Drp.DataBind

End While
Thanks

Hi websyd,

I'm not quite sure why you need to put the databinding process in a loop.

Are you trying to put every row into the dropdownlist item collection? If so, please forget about the loop. When you have set the DataSource, DataTextField and DataValueField, the binding process will put everything into the collection automatically.

So please change to

Drp.DataSource = MyDataSet.Tables("Products")
Drp.DataTextField = "ProductName"
Drp.DataValueField = "ProductId"
Drp.DataBind()

And for DataReader, you can use

Dim Drp as New DropDownList
Drp.Id="Drp"
Drp.DataSource=MyReader
Drp.DataTextField="ProductName"
Drp.DataValueField="ProductId"
Drp.DataBind

HTH.

|||

Hi thanks 4 d response. I looped because i needed to create the DropDowns based on the number of rows in the table. So if i remove the code from the loop i will get only one DropDownList as your code suggests.

With the DataReader, again this will create only one DropDownList but i need to create to more than one.

Thanks

|||

Hi Websyd,

The DataReader only created one DropDownList because the DataReader can only be used once in data binding.

This is because when bound, the control will have the DataReader read to the end to populate the items. As you know, the DataReader is forward-only and cannot be used again for reading. That's why only one control is filled with data.

Sunday, February 19, 2012

How to do an update on existing records?

I have one table of new records (tableA) that may already exist in
tableB. I want to insert these records into tableB with insert if they
don't already exist, or update any existing ones with new data if they
do already exist. A column (Action) in tableA already tells me whether
this is an INSERT, UPDATE, or DELETE. I'm able to derive that I can do
an insert with

select * into tableB from tableA where Action = 'INSERT'

...and I think I can handle the delete.

But I'm stuck on the update. How do I do the update? An ordinary
UPDATE statement just won't do unless I use a cursor to cycle through
the recordset. I want to avoid a cursor."Google Mike" <googlemike@.hotpop.com> wrote in message
news:25d8d6a8.0402231212.16ab7593@.posting.google.c om...
> I have one table of new records (tableA) that may already exist in
> tableB. I want to insert these records into tableB with insert if they
> don't already exist, or update any existing ones with new data if they
> do already exist. A column (Action) in tableA already tells me whether
> this is an INSERT, UPDATE, or DELETE. I'm able to derive that I can do
> an insert with
> select * into tableB from tableA where Action = 'INSERT'
> ...and I think I can handle the delete.
> But I'm stuck on the update. How do I do the update? An ordinary
> UPDATE statement just won't do unless I use a cursor to cycle through
> the recordset. I want to avoid a cursor.

I don't completely understand your description, and it would be useful to
see the structure of your tables (ie CREATE TABLE statements), as well as
some sample data. However, here is a fairly generic solution - if it doesn't
work as you expect, then please consider posting the additional information.

/* INSERT new records */

insert into dbo.tableB (col1, col2, ...)
select col1, col2, ...
from dbo.tableA a
where not exists
(select * from dbo.tableB b
where a.PrimaryKeyCol = b.PrimaryKeyCol)
and a.[Action] = 'INSERT'

/* UPDATE existing records */

update dbo.tableB
set col1 = a.col1, col2 = a.col2, ...
from dbo.tableB b
join dbo.tableA a
on a.PrimaryKeyCol = b.PrimaryKeyCol
where a.[Action] = 'UPDATE'

/* DELETE existing records */

delete from dbo.tableB
where exists
(select * from dbo.tableA a
where a.PrimaryKeyCol = dbo.tableB.PrimaryKeyCol
and a.[Action] = 'DELETE')

Note that 'Action' is listed in "Reserved Keywords" as a word to avoid using
in code (at least in SQL 2000 Books Online - you didn't mention which
version of MSSQL you're using).

Simon