2012-07-14 95 views
3

我有一个大客户数据库,其中客户表包含人员及其与组织的关系。人们可能属于多个组织(这允许组织内部的分区)。具有多个组织的人员必须具有默认组织,这通常由isDefault = T决定,但前端应用程序也可以通过选择MIN(RowID)来确定isDefault = F的默认应用程序。SQL选择值='X'或最小值

因此,在表中我们知道PersonId3有一个默认的11OrgID(ISDEFAULT = T) 但是,我需要弄清楚查询查找是PersonID 12的默认。 即

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

如果0行返回然后执行这样的查询:

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 
+1

什么是您的RDBMS? MySql,MS Sql,Oracle? – rcdmk 2012-07-14 01:21:06

+0

MS SQL 2008.它是实际表的总结,但应该足以让某个人比我更聪明;-) – Xardax99 2012-07-14 01:26:31

+0

@ Xardax99是否有可能有这样的一行? 5 | 3 | 17 | F ?我的意思是,如果'PersonID = 3'有2个OrgID(*,其中IsDefault = F *)会返回什么? – 2012-07-14 01:31:34

回答

2

我想你可以通过是否ISDEFAULT订货两次,第一次得到你想要的为T或F,然后通过RowId的,并采取顶部结果:

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

+1非常聪明,你是。你有的力量。 – rcdmk 2012-07-14 01:46:18

+0

令人敬畏的工作,简短,甜蜜和工作。感谢您的协助 – Xardax99 2012-07-14 04:35:09

+0

@ Xardax99 - 确保使用此查询的记录数量较少,否则对“Order clause”中单个记录的决策(排序)可能会产生“性能问题”。 – 2012-07-14 04:48:27

0

此逻辑成一个查询是相当复杂的。你必须把所有的结果联合起来,记录结果来自哪里。然后你必须计算第一部分有多少行,并且只保留适当结果集中的行。

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 

如果您可以使用T-SQL,而不是一个单一的查询,那么你可以只运行的第一个版本,检查结果的行数,然后决定哪些结果集取。

+0

哇,有一天我希望了解这个查询;-)感谢您的帮助 – Xardax99 2012-07-14 04:43:47

1

在MySQL服务器,你可以做一个联盟与限制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; 

对于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; 
+0

感谢rcdmk,效果很好,我已经给Bort答案,因为他的查询更短,但你的工作也很好,所以再次感谢您的帮助 – Xardax99 2012-07-14 04:41:35

1

没试过执行这一点,但希望这个S会工作。 IsDefault将短路子查询。

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 
          ) 
     ) 
+0

感谢Shantanu,当我对一个确实有'isDefault'和多个orgID的人进行测试时,它返回了所有的orgIds。感谢您的帮助,虽然 – Xardax99 2012-07-14 04:37:02

0

请试试这个

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 
+0

感谢乔,这些人不返回具有多个OrgIds和isDefault ='T'的personID。欢呼虽然帮助。 – Xardax99 2012-07-14 04:39:57

+0

@ Xardax99:我已更新查询请chaeck – 2012-07-14 06:00:29

0

这取决于表有多大什么是indexes.If说ROWID具有唯一聚集索引 和PERSONID和ISDEFAULT有我将使用两个数控指数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