tags:

views:

47

answers:

4

Hi all,

I have a table that looks something like this:

ID         | GROUP
-------------------
1000001    | 0
1000001    | 1
1000001    | 2
1000002    | 0
1000002    | 2
1000002    | 3
1000003    | 1
1000003    | 2
1000003    | 3
1000004    | 0

I need to list all the ids where there is a group missing in the sequence. So for the above example i would only need back 1000002 & 1000003.

Thanks in advance

A: 

Maybe this:

SELECT
  id
FROM mytable m
GROUP BY id
HAVING (MAX(group) + 1) > COUNT(DISTINCT group);

(I've written the keys in lowercase). If you have a unique key on (ID, GROUP), you can leave out the DISTINCT.

Martijn
@Martijn, may be need 'group by id', not a 'group by group'?
Michael Pakhantsov
lol. Glad I saw your comment, had to go fix mine. :)
XstreamINsanity
@XstreamINsanity, Correct query is SELECT distinct id from table GROUP BY id HAVING MAX(group) + 1 > (COUNT(DISTINCT group));
Michael Pakhantsov
Thanks, edited my answer.
XstreamINsanity
@Michael: you're absolutely right (both times). I posted this answer a bit too quick.
Martijn
+2  A: 
select distinct id
from
(
    SELECT Id, Group, LAG(Group, 1, -1) over (partition by Id order by Group) prevGroup
 FROM Table
 )     
 WHERe Group -1 <> PrevGroup
Michael Pakhantsov
Wow, looking at this answer makes me feel like I don't know SQL at all. :) I have no idea what LAG or partition are or how they'd be used.
XstreamINsanity
@XstreamINsanity, LAG provides access to more than one row of a table at the same time without a self-join. Given a series of rows returned from a query and a position of the cursor, LAG provides access to a row at a given physical offset prior to that position.Look to http://psoug.org/reference/analytic_functions.html
Michael Pakhantsov
Thanks, that's some knowledge for the future.
XstreamINsanity
in your defense, it's pretty new-ish. I think the Oracle analytics first came out when 9i did, and even theyn they were only in Enterprise Edition.
Adam Musch
A: 

What I'm getting from your comments is that the ID must start with a group of 0 and the group should always increment only by 1. From that, I get this:

SELECT id
FROM (
        SELECT  id, count(*) as cnt, max(group) as mx, min(group) as mn
        FROM    myTable
        GROUP BY group
     ) A
WHERE NOT mx = cnt - 1
AND NOT mn = 0

Hope this helps. It's probably not the cleanest or most effective, but hope it will help.

EDIT: Actually, after re-looking over the answer before mine and thinking about HAVING, it probably would be cleaner like this.

SELECT ID
FROM   myTable
GROUP BY ID
HAVING MAX(group) >= COUNT(DISTINCT group)
XstreamINsanity
+2  A: 

As we don need the information about the missing group number we can compare that over all count of elements is lower or equal for specific group

SELECT ID FROM YOUR_TABLE
GROUP BY ID 
HAVING COUNT(ID) <= max(GROUP);
Vash
+1 Like yours better than mine. :)
XstreamINsanity
Thank You. ''''''
Vash