473,386 Members | 1,715 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

SQL statement question

Hello group,

I have a table with the next contents.
It lists data about : Who sent what kind of message at what time.
For the Level column: The highest level is Critical, the middle is Warning,
the lowest is Info.

Id Timestamp Level
1 12:00 Info
1 13:00 Warning
1 14:00 Critical
2 12:00 Info
2 13:00 Warning
2 14:00 Info
2 15:00 Warning
3 12:00 Critical
3 13:00 Warning
4 15:00 Info
5 15:00 Info
5 16:00 Warning

What I want to get out of his list is:
The first message with the highest level of each Id. So let the Level-column
prevail above the Timestamp column,so I want to get this result:

1 14:00 Critical // The only 'Critical'
2 13:00 Warning // the first 'Warning'
3 12:00 Critical // The only 'Critical'
4 15:00 Info // The only one, so simple
5 16:00 Warning // The highest level, the only
'Warning'
So: First find the highest level of message of each Id and then find the
first one.
The first part I tried with CASE .. THEN .. END construction.

Any hints appreciated.

Gr, Hans
Jul 20 '05 #1
6 2029
"Siemel Naran" <Si*********@REMOVE.att.net> wrote in message
news:S%8Oc.151848
"Hans" <ni*********@zonnet.nl> wrote in message news:4108fb97$0$93324
"Leif" <id****@internet.dk> wrote in message
select id,min(time),level from table a where (id,level) in (select
id,max(level) from table b group by b.id) group by a.id
BTW-2 The query you propesed is running now for more than an hour, so
What is the exact query you ran? I think MySql supports function indexes,
so for example you could try to create index (id, case level when 'High'
then 3 ... end), or create index (id, if(level='High', 3, if(...))). Will
need to look it up, but have to run to work.
So I checked, and no, MySql 4.1 and even 5.0 I think, does not support
function indexes.
Also, what does the query plan say is the driving table and index?


The above is important, because it could mean the difference between a query
that returns right away, and another that takes hours.

In Leif's original query, I think you would need only one index. This
assumes driving by the inner query is the right thing for your situation
(which may or may not be the case), and that MySql will in this case indeed
drive by the inner query.

create index table_level on table (id, level);

But this only works when the level numbers are 1 for Critical, 2 for
Warning, 3 for Info. By contrast, sorting level as strings yields Critical,
Info, Warning -- which is not correct.
One solution is function indices, which some databases provide, but not
MySql. It would look like this:

create index table_level on table (id, case level when 'Critical' then 1 ...
end);
Most databases support triggers, but MySql only will in 5.1. It would look
something like this:

create trigger on table
for update
as update table set levelnum = case level when 'Critical' then 1 ... end;

create index table_level on table (id, levelnum);
Some databases also let you define calculated fields, so you'd say

create table (
level varchar(10) not null,
levelnum smallint(1) as case level when 'Critical' then 1 ... end,
index on table (id, levelnum);
);

But I don't think MySql does not let you do this either.
Of course, you could just add your levelnum column and when you insert or
update table.level, remember to update levelnum too. So you'd have to put
more work into the PHP or C++ scripts, or whatever, that take input from the
user and convert these into SQL statements.
Another design decision is to set level = "1 - Critical", "2 - Warning",
etc. It's nice for the end user too. We use it at work, and it works
nicely. Then Leif's original solution plus the index should work. You
could create an index the first char of table.level.
The problem with

select id,max(case level when ... end) from table b group by b.id

is that the system will still scan all rows and evaluate (case level ...
end) because it does not know that once it has seen a 'Critical' it can't
see anything higher. Plus, without a function or index or index on a
calculated column, it has no index to immediately locate the records of
importance, so it has to do a full table scan.
Still, maybe we could use collations. Something like

create table (
level varchar(10) not null character set collate <an appropriate name>
)

The <an appropriate name> is a collation where Critical comes first, then
Warning, then Info. But I don't know how to create new collations.
Jul 20 '05 #2

"Hans" <ni*********@zonnet.nl> skrev i en meddelelse
news:41***********************@news.xs4all.nl...
Hello group,

I have a table with the next contents.
It lists data about : Who sent what kind of message at what time.
For the Level column: The highest level is Critical, the middle is Warning, the lowest is Info.

Id Timestamp Level
1 12:00 Info
1 13:00 Warning
1 14:00 Critical
2 12:00 Info
2 13:00 Warning
2 14:00 Info
2 15:00 Warning
3 12:00 Critical
3 13:00 Warning
4 15:00 Info
5 15:00 Info
5 16:00 Warning

What I want to get out of his list is:
The first message with the highest level of each Id. So let the Level-column prevail above the Timestamp column,so I want to get this result:

1 14:00 Critical // The only 'Critical'
2 13:00 Warning // the first 'Warning'
3 12:00 Critical // The only 'Critical'
4 15:00 Info // The only one, so simple 5 16:00 Warning // The highest level, the only
'Warning'
So: First find the highest level of message of each Id and then find the
first one.

I hope the level is an enum, so you can sort on it.

Will this work?

select id,min(time),level from table a where (id,level) in (select
id,max(level) from table b group by b.id) group by a.id

Leif
Jul 20 '05 #3

"Leif" <id****@internet.dk> wrote in message
news:41**********************@nntp03.dk.telia.net. ..

"Hans" <ni*********@zonnet.nl> skrev i en meddelelse
news:41***********************@news.xs4all.nl...
Hello group,


I hope the level is an enum, so you can sort on it.
Nope.
Will this work?

select id,min(time),level from table a where (id,level) in (select
id,max(level) from table b group by b.id) group by a.id


That's a query that will cost a lot of time for multiple 1000s of records.

I already found a solution myself; I created a new table with the
'enum'-values of all levels ,MessageLevels:
Value Name
1 Info
2 Warning
3 Critical

And thenthis query:
SELECT
`SubQuery`.`Id_1`,
`MessageLevels`.`Name`
FROM (
SELECT
`MyTable`.`Id` AS `Id_1`,
`MessageLevels`.`Value` AS `Message_Value`
FROM
`MyTable`
INNER JOIN `MessageLevels` ON (`MyTable`.`Name` = `MessageLevels`.`Name`)
ORDER BY `Id`,
`Message_Value` DESC
) AS `SubQuery`
INNER JOIN
`MessageLevels` ON (`SubQuery`.`Message_Value` = `MessageLevels`.`Value`)
GROUP BY `SubQuery`.`Id_1`
Which in the subquery creates a table with all ID's with ALL their
messagelevels, sorted by ID, and then MessageLevel DESC,
And the from this subquery's result, id do GROUP BY Id, which causes only
the first record for each Id to be selected.

BTW This is not exactly what I asked in my first post, (No timestamp) but it
is indeed what I want ;-)

BTW-2 The query you propesed is running now for more than an hour, so that's
not really a good solution, but thanks anyway for thinking with me.

Gr, Hans
Jul 20 '05 #4

"Leif" <id****@internet.dk> wrote in message
news:41**********************@nntp03.dk.telia.net. ..

"Hans" <ni*********@zonnet.nl> skrev i en meddelelse
news:41***********************@news.xs4all.nl...
Hello group,


I hope the level is an enum, so you can sort on it.
Nope.
Will this work?

select id,min(time),level from table a where (id,level) in (select
id,max(level) from table b group by b.id) group by a.id


That's a query that will cost a lot of time for multiple 1000s of records.

I already found a solution myself; I created a new table with the
'enum'-values of all levels ,MessageLevels:
Value Name
1 Info
2 Warning
3 Critical

And thenthis query:
SELECT
`SubQuery`.`Id_1`,
`MessageLevels`.`Name`
FROM (
SELECT
`MyTable`.`Id` AS `Id_1`,
`MessageLevels`.`Value` AS `Message_Value`
FROM
`MyTable`
INNER JOIN `MessageLevels` ON (`MyTable`.`Name` = `MessageLevels`.`Name`)
ORDER BY `Id`,
`Message_Value` DESC
) AS `SubQuery`
INNER JOIN
`MessageLevels` ON (`SubQuery`.`Message_Value` = `MessageLevels`.`Value`)
GROUP BY `SubQuery`.`Id_1`
Which in the subquery creates a table with all ID's with ALL their
messagelevels, sorted by ID, and then MessageLevel DESC,
And the from this subquery's result, id do GROUP BY Id, which causes only
the first record for each Id to be selected.

BTW This is not exactly what I asked in my first post, (No timestamp) but it
is indeed what I want ;-)

BTW-2 The query you propesed is running now for almost 45 minutes, so that's
not really a good solution, but thanks anyway for thinking with me.

Gr, Hans

Jul 20 '05 #5
"Hans" <ni*********@zonnet.nl> wrote in message news:4108fb97$0$93324
"Leif" <id****@internet.dk> wrote in message
Will this work?

select id,min(time),level from table a where (id,level) in (select
id,max(level) from table b group by b.id) group by a.id


That's a query that will cost a lot of time for multiple 1000s of records.

BTW-2 The query you propesed is running now for more than an hour, so that's not really a good solution, but thanks anyway for thinking with me.


What is the exact query you ran? I think MySql supports function indexes,
so for example you could try to create index (id, case level when 'High'
then 3 ... end), or create index (id, if(level='High', 3, if(...))). Will
need to look it up, but have to run to work.

Also, what does the query plan say is the driving table and index?
Jul 20 '05 #6
"Siemel Naran" <Si*********@REMOVE.att.net> wrote in message
news:S%8Oc.151848
"Hans" <ni*********@zonnet.nl> wrote in message news:4108fb97$0$93324
"Leif" <id****@internet.dk> wrote in message
select id,min(time),level from table a where (id,level) in (select
id,max(level) from table b group by b.id) group by a.id
BTW-2 The query you propesed is running now for more than an hour, so
What is the exact query you ran? I think MySql supports function indexes,
so for example you could try to create index (id, case level when 'High'
then 3 ... end), or create index (id, if(level='High', 3, if(...))). Will
need to look it up, but have to run to work.
So I checked, and no, MySql 4.1 and even 5.0 I think, does not support
function indexes.
Also, what does the query plan say is the driving table and index?


The above is important, because it could mean the difference between a query
that returns right away, and another that takes hours.

In Leif's original query, I think you would need only one index. This
assumes driving by the inner query is the right thing for your situation
(which may or may not be the case), and that MySql will in this case indeed
drive by the inner query.

create index table_level on table (id, level);

But this only works when the level numbers are 1 for Critical, 2 for
Warning, 3 for Info. By contrast, sorting level as strings yields Critical,
Info, Warning -- which is not correct.
One solution is function indices, which some databases provide, but not
MySql. It would look like this:

create index table_level on table (id, case level when 'Critical' then 1 ...
end);
Most databases support triggers, but MySql only will in 5.1. It would look
something like this:

create trigger on table
for update
as update table set levelnum = case level when 'Critical' then 1 ... end;

create index table_level on table (id, levelnum);
Some databases also let you define calculated fields, so you'd say

create table (
level varchar(10) not null,
levelnum smallint(1) as case level when 'Critical' then 1 ... end,
index on table (id, levelnum);
);

But I don't think MySql does not let you do this either.
Of course, you could just add your levelnum column and when you insert or
update table.level, remember to update levelnum too. So you'd have to put
more work into the PHP or C++ scripts, or whatever, that take input from the
user and convert these into SQL statements.
Another design decision is to set level = "1 - Critical", "2 - Warning",
etc. It's nice for the end user too. We use it at work, and it works
nicely. Then Leif's original solution plus the index should work. You
could create an index the first char of table.level.
The problem with

select id,max(case level when ... end) from table b group by b.id

is that the system will still scan all rows and evaluate (case level ...
end) because it does not know that once it has seen a 'Critical' it can't
see anything higher. Plus, without a function or index or index on a
calculated column, it has no index to immediately locate the records of
importance, so it has to do a full table scan.
Still, maybe we could use collations. Something like

create table (
level varchar(10) not null character set collate <an appropriate name>
)

The <an appropriate name> is a collation where Critical comes first, then
Warning, then Info. But I don't know how to create new collations.
Jul 20 '05 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: Greg Ofiesh | last post by:
Anyone who can help, I have two tables T1 and T2. T1 has fields K1 and F2 and T2 has fields K2 and F1. F1 is the foreign key relating to K1 and F2 is the foreign key relating to K2. My...
94
by: John Bailo | last post by:
The c# *return* statement has been bothering me the past few months. I don't like the fact that you can have different code paths in a method and have multiple return statements. To me, it...
9
by: Michael | last post by:
Hi all, I would like to get people's opinion about executing SQL statements in C# (or any other .NET language really). I used to create my SQL statement by building a string and replacing single...
7
by: Steven Bethard | last post by:
I've updated PEP 359 with a bunch of the recent suggestions. The patch is available at: http://bugs.python.org/1472459 and I've pasted the full text below. I've tried to be more explicit about...
1
by: javedna | last post by:
Can PHP help with the following as I have tried in the MYSQL Forums and cant get any help Thanks Nabz ---------------------------------------- Hi I am developing a PHP MYSQL questionnaire...
26
by: a.mil | last post by:
I am programming for code-speed, not for ansi or other nice-guy stuff and I encountered the following problem: When I have a for loop like this: b=b0; for (a=0,i=0;i<100;i++,b--) { if (b%i)...
18
by: dspfun | last post by:
Hi! The words "expression" and "statement" are often used in C99 and C- textbooks, however, I am not sure of the clear defintion of these words with respect to C. Can somebody provide a sharp...
23
by: florian.loitsch | last post by:
According to the spec Section 14 the production SourceElements:SourceElements SourceElement is evaluated as follows: 1. Evaluate SourceElements. 2. If Result(1) is an abrupt completion, return...
21
beacon
by: beacon | last post by:
Hello to everybody, I have a section on a form that has 10 questions, numbered 1-10, with 3 option buttons per question. Each of the option buttons have the same response (Yes, No, Don't know),...
10
by: JohnO | last post by:
Hi All, This question is related to iSeries V5R4 and db2. I want to implement an AFTER DELETE trigger to save the deleted rows to an archive table, I initially defined it as a FOR EACH...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.