2

Problem Definition

I have an SQL query that looks like:

SELECT *
    FROM table
    WHERE criteria = 1
    ORDER BY group;

Result

I get:

group | value | criteria
------------------------
  A   |  0    |   1
  A   |  1    |   1
  B   |  2    |   1
  B   |  3    |   1

Expected Result

However, I would like to limit the results to only the first group (in this instance, A). ie,

group | value | criteria
------------------------
  A   |  0    |   1
  A   |  1    |   1

What I've tried

Group By

SELECT *
    FROM table
    WHERE criteria = 1
    GROUP BY group;

I can aggregate the groups using a GROUP BY clause, but that would give me:

group | value
-------------
  A   |  0
  B   |  2

or some aggregate function of EACH group. However, I don't want to aggregate the rows!

Subquery

I can also specify the group by subquery:

SELECT *
  FROM table
 WHERE criteria = 1 AND 
       group = (
                       SELECT group
                         FROM table
                        WHERE criteria = 1
                        ORDER BY group ASC
                        LIMIT 1
                   );

This works, but as always, subqueries are messy. Particularly, this one requires specifying my WHERE clause for criteria twice. Surely there must be a cleaner way to do this.

Shadowen
  • 838
  • 5
  • 14

3 Answers3

2

You can try following query:-

SELECT *
FROM table
WHERE criteria = 1
AND group = (SELECT MIN(group) FROM table)
ORDER BY value;
Ankit Bajpai
  • 13,128
  • 4
  • 25
  • 40
  • 2
    I think he wants the first group that meets his criteria, not the first group overall. – APH Aug 21 '15 at 15:49
1

If your database supports the WITH clause, try this. It's similar to using a subquery, but you only need to specify the criteria input once. It's also easier to understand what's going on.

with main_query as (
  select *
  from table
  where criteria = 1
  order by group, value
),
with min_group as (
  select min(group) from main_query
)
select *
from main_query
where group in (select group from min_group);
  -- this where clause should be fast since there will only be 1 record in min_group
Matt
  • 828
  • 8
  • 25
0

Use DENSE_RANK()

DECLARE @yourTbl AS TABLE (
    [group] NVARCHAR(50),
    value INT,
    criteria INT
)

INSERT INTO @yourTbl VALUES ( 'A', 0, 1 )
INSERT INTO @yourTbl VALUES ( 'A', 1, 1 )
INSERT INTO @yourTbl VALUES ( 'B', 2, 1 )
INSERT INTO @yourTbl VALUES ( 'B', 3, 1 )

;WITH cte AS
(
   SELECT i.* , 
   DENSE_RANK() OVER (ORDER BY i.[group]) AS gn
   FROM @yourTbl AS i
   WHERE i.criteria = 1
)
SELECT *
FROM cte
WHERE gn = 1


group | value | criteria
------------------------
A     | 0     | 1     
A     | 1     | 1   
minhhungit
  • 180
  • 4
  • 25