开发者

DB Query. How to capture 'mixed' status on a single row

开发者 https://www.devze.com 2023-03-10 15:53 出处:网络
I have a database query ... select foo, bar, status from mytable where bar in (bar1, bar2, bar3); The status is a status associated with the pair foo-bar. The GUI display is going to display 1 ro

I have a database query ...

select foo, bar, status 
    from mytable 
    where bar in (bar1, bar2, bar3);

The status is a status associated with the pair foo-bar. The GUI display is going to display 1 row fo开发者_C百科r every foo, and should display a checked-checkbox if for all bar1, bar2, bar3 for that foo, the status are all 1. And an unchecked chceckbox if for that foo, the status values of bar1, bar2 and bar3 are all zero. If, again for a given foo, different bars have a different status, I am required to display some other token (a questionmark, say.)

My knowledge of sql isn't sufficient to this task. Can this be done in sql. it's in Oracle, if that makes a difference. I'm thinking I may have to suck it into perl and check for the condition there, but I'm not happy with that idea.


In T-SQL I'd do this:

create table mytable (foo nvarchar(128), bar nvarchar(128), status int)
go
select foo, (MAX(status) + MIN(status)) as status 
from mytable 
group by foo

then in the client app the resulting status value will be 0 if all are unchecked, 1 if some checked, and 2 if all checked


With a CTE to supply sample data, different combinations of zeros and ones in the row statuses gives different output values:

with tmp_tab as (
    select 'foo1' as foo, 'bar1' as bar, 0 as status from dual
    union
    select 'foo1' as foo, 'bar2' as bar, 0 as status from dual
    union
    select 'foo1' as foo, 'bar3' as bar, 0 as status from dual
    union
    select 'foo2' as foo, 'bar1' as bar, 0 as status from dual
    union
    select 'foo2' as foo, 'bar2' as bar, 1 as status from dual
    union
    select 'foo2' as foo, 'bar3' as bar, 0 as status from dual
    union
    select 'foo3' as foo, 'bar1' as bar, 1 as status from dual
    union
    select 'foo3' as foo, 'bar2' as bar, 1 as status from dual
    union
    select 'foo3' as foo, 'bar3' as bar, 1 as status from dual
)
select foo,
    case
        when sum(status) = 0 then 'Unchecked'
        when sum(status) = count(bar) then 'Checked'
        else 'Unknown'
    end as status
from tmp_tab
where bar in ('bar1','bar2','bar3')
group by foo;

FOO  STATUS
---- ---------
foo1 Unchecked
foo2 Unknown
foo3 Checked


perhaps restructure your query to perform a union instead of the IN.

in that way, you will have an explicit value (unique to each unioned select statement, that will tell you which value has been matched.


If the designer were smart, bar1, bar2, and bar3 should be numeric powers of 2, so one can apply bitwise operators to them - then it would be trivial to know which of the particular bars are set.


I'm assuming bar1/2/3 can only be 0 or 1:

SELECT foo, bar,
       CASE WHEN ( bar1 + bar2 + bar3 = 3 ) THEN 'checked'
            WHEN ( bar1 + bar2 + bar3 = 0 ) THEN 'unchecked'
            ELSE 'something else' END
  FROM mytable 
 WHERE bar in (bar1, bar2, bar3);

Or am I missing something?

Edit: Looks like I originally misunderstood the problem. I think this will work.

SELECT foo,
       DECODE( sum_status, 0, 'unchecked', 3, 'checked', 'something else' )
  FROM ( SELECT foo, SUM( status ) AS sum_status
           FROM mytable
          WHERE bar in (bar1, bar2, bar3)
          GROUP BY foo )

Again, this assumes status can only be 0 or 1.

0

精彩评论

暂无评论...
验证码 换一张
取 消