简体   繁体   中英

SQL Select where value = 'X' or min value

I have a large customer database where the customer table has people and their relationship to an organisation. People may belong to multiple organisations ( this allows divisions within organisations ). People with multiple organisations must have a default organisation, this is usually determined where isDefault = T , however the front end application can also figure the default application where isDefault = F by selecting the MIN(RowID) .

So in the table below we know PersonId 3 has a default OrgID of 11 (IsDefault = T) However, I need to figure out the query for finding PersonID 12's default. ie

Select orgId as default from myTable
where personID = 12
and isDefault = 'T'

If 0 rows returned then perform a query like this:

Select orgId as default from myTable
where personID = 12
and 
RowId in (select Min(rowId) 
from myTable 
where PersonId = 12)


RowID | PersonID  | OrgId  |  isDefault
1     |    12     |   14   |     F
2     |    12     |   17   |     F
3     |    3      |   11   |     T
4     |    3      |   14   |     F

I think you can get what you want by ordering twice, first by whether IsDefault is T or F, then by RowId, and take the top result:

SELECT TOP 1 OrgId as [Default]
FROM MyTable
WHERE PersonId = 12
ORDER BY
    CASE WHEN IsDefault = 'T' THEN 0 ELSE 1 END,
    RowId

In MySql server you can do a union with limit 1:

SELECT OrgId AS `default`
FROM (
    SELECT OrgId FROM MyTable
    WHERE PersonID = 12
    and isDefault = 'T'

    UNION

    SELECT OrgId FROM MyTable
    WHERE PersonId = 12
    AND RowId in (
        SELECT MIN(RowId)
        FROM MyTable
        WHERE PersonId = 12
    )
) SomeName LIMIT 1;

For SQL Server:

SELECT TOP 1 OrgId AS [default]
FROM (
    SELECT OrgId FROM MyTable
    WHERE PersonID = 12
    and isDefault = 'T'

    UNION

    SELECT OrgId FROM MyTable
    WHERE PersonId = 12
    AND RowId in (
        SELECT MIN(RowId)
        FROM MyTable
        WHERE PersonId = 12
    )
) SomeName;

Didn't tried executing this but expecting this should work. IsDefault will short circuit the subquery.

  Select orgId as default from myTable o
   where personID = 12 
       and  
       ( IsDefault = 'T' OR
                   RowId = (select Min(rowId)  
                               from myTable i
                             where i.PersonId = o.PersonId
                           )  
        )

Putting this logic into one query is rather complicated. You have to union all the results together, keeping track of where the result come from. Then you have to count how many rows come from the first part, and keep only the rows from the appropriate result set.

select orgid, mytable
from (select t.*, sum(which) over (partition by null) as whichcnt
      from ((Select 1 as which, orgId as default
             from myTable
             where personID = 12 and
                   isDefault = 'T'
            )
            union all
           (Select 0 as which, orgId as default
            from myTable
            where personID = 12 and 
                  RowId in (select Min(rowId) from myTable where PersonId = 12)
           )
          ) t
     ) t
where whichcnt > 0 and which = 1 or whichcnt = 0

If you can use TSQL instead of of a single query, then you can just run the first version, check the number of rows in the results, and then decide which result set to take.

Please try this

select PersonID ,OrgID from mytable where isDefault='T'
union all

select personID,min(OrgID) [default]
from myTable P
where  not exists 
(select * from mytable C where P.PersonID=C.PersonID and C.isDefault='T')
group by personID

It depends on how big the table is what are the indexes.If say rowid has unique clustered index and personid and isdefault has a nc index I will use two statemnts.

 declare @orgid int = null
 select @orgid =orgid from table where personid = 12 and isdefault = 'T'
 if (orgid  is null)
 begin
 select @orgid = orgid 
 from mytable
 where rowid = (
 select min(rowid)from table where personid = 12 and isdefault = 'F'
 )
 end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM