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.