Use of Where and having clause

Hi all,
I always have a doubt about use of HAVING and WHERE clause,
suppose I have table T1 with only one column C1
CREATE TABLE T1
(C1 VARCHAR2(1) );
which having data by following INSERT scripts
INSERT INTO T1 VALUES('A');
INSERT INTO T1 VALUES('B');
INSERT INTO T1 VALUES('C');
INSERT INTO T1 VALUES('A');
INSERT INTO T1 VALUES('B');
INSERT INTO T1 VALUES('A');
Now I want result as follows
C1 ==== COUNT(C1)
==============
B ===== 2
A ===== 3
So out of query 1 and 2 which approach is right ?
1) SELECT C1,COUNT(C1) FROM T1
WHERE C1<>'C'
GROUP BY C1
ORDER BY C1 DESC;
2) SELECT C1,COUNT(C1) FROM T1
GROUP BY C1
HAVING C1<>'C'
ORDER BY C1 DESC;
Edited by: user13306874 on Jun 21, 2010 2:36 AM

In SQL, it's always best to filter data at the earliest moment possible.
In your example the WHERE clause would be that moment:
SQL> explain plan for
  2  select c1,count(c1)
  3  from t1
  4  where c1 != 'C'
  5  group by c1
  6* order by c1 desc;
Explained.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
Plan hash value: 3946799371
| Id  | Operation          | Name | Rows  | Bytes |
|   0 | SELECT STATEMENT   |      |     5 |    10 |
|   1 |  SORT GROUP BY     |      |     5 |    10 |
|*  2 |   TABLE ACCESS FULL| T1   |     5 |    10 |
Predicate Information (identified by operation id):
   2 - filter("C1"!='C')
18 rows selected.
SQL>As you can see the filter is applied during the scan of T1.
Whereas in the HAVING case:
SQL> explain plan for
  2  select c1,count(c1)
  3  from t1
  4  group by c1
  5  having c1 != 'C'
  6* order by c1 desc;
Explained.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
Plan hash value: 3146800528
| Id  | Operation           | Name | Rows  | Bytes |
|   0 | SELECT STATEMENT    |      |     6 |    12 |
|*  1 |  FILTER             |      |       |       |
|   2 |   SORT GROUP BY     |      |     6 |    12 |
|   3 |    TABLE ACCESS FULL| T1   |     6 |    12 |
Predicate Information (identified by operation id):
   1 - filter("C1"!='C')
18 rows selected.
SQL>The scan is done after all groups have been computed: one of which was computed in vain, since it will be filtered away due to the HAVING clause.
In general I would use as a guideline: if you are not using aggregate functions in your HAVING clause predicate, then move that predicate to the WHERE portion of your query.
Edited by: Toon Koppelaars on Jun 21, 2010 11:54 AM

Similar Messages

  • Which two statements are true about WHERE and HAVING clause ?

    Which two statements are true about WHERE and HAVING clause ?
    1. WHERE clause can be used to restict rows only
    2.HAVING clause can be used to restrict groups only
    3.HAVING clause can be used to restrict groups and rows
    Plz help me in dis ques...which two will be correct...i think its 1 and 2...but not sure.

    863180 wrote:
    Plz help me in dis ques...which two will be correct...i think its 1 and 2...but not sure.If you are not sure then you do not fully understand HAVING.
    SY.

  • Group by clause and having clause in select

    hi frnds
    plz give me some information of group by and having clause used in select statement with example
    thanks

    The Open SQL statement for reading data from database tables is:
    SELECT      <result>
      INTO      <target>
      FROM      <source>
      [WHERE    <condition>]
      [GROUP BY <fields>]
      [HAVING   <cond>]
      [ORDER BY <fields>].
    The SELECT statement is divided into a series of simple clauses, each of which has a different part to play in selecting, placing, and arranging the data from the database.
    You can only use the HAVING clause in conjunction with the GROUP BY clause.
    To select line groups, use:
    SELECT <lines> <s1> [AS <a1>] <s2> [AS <a2>] ...
                   <agg> <sm> [AS <am>] <agg> <sn> [AS <an>] ...
           GROUP BY <s1> <s2> ....
           HAVING <cond>.
    The conditions <cond> that you can use in the HAVING clause are the same as those in the SELECT clause, with the restrictions that you can only use columns from the SELECT clause, and not all of the columns from the database tables in the FROM clause. If you use an invalid column, a runtime error results.
    On the other hand, you can enter aggregate expressions for all columns read from the database table that do not appear in the GROUP BY clause. This means that you can use aggregate expressions, even if they do not appear in the SELECT clause. You cannot use aggregate expressions in the conditions in the WHERE clause.
    As in the WHERE clause, you can specify the conditions in the HAVING clause as the contents of an internal table with line type C and length 72.
    Example
    DATA WA TYPE SFLIGHT.
    SELECT   CONNID
    INTO     WA-CONNID
    FROM     SFLIGHT
    WHERE    CARRID = 'LH'
    GROUP BY CONNID
    HAVING   SUM( SEATSOCC ) > 300.
      WRITE: / WA-CARRID, WA-CONNID.
    ENDSELECT.
    This example selects groups of lines from database table SFLIGHT with the value ‘LH’ for CARRID and identical values of CONNID. The groups are then restricted further by the condition that the sum of the contents of the column SEATSOCC for a group must be greater than 300.
    The <b>GROUP BY</b> clause summarizes several lines from the database table into a single line of the selection.
    The GROUP BY clause allows you to summarize lines that have the same content in particular columns. Aggregate functions are applied to the other columns. You can specify the columns in the GROUP BY clause either statically or dynamically.
    Specifying Columns Statically
    To specify the columns in the GROUP BY clause statically, use:
    SELECT <lines> <s1> [AS <a 1>] <s 2> [AS <a 2>] ...
                   <agg> <sm> [AS <a m>] <agg> <s n> [AS <a n>] ...
           GROUP BY <s1> <s 2> ....
    To use the GROUP BY clause, you must specify all of the relevant columns in the SELECT clause. In the GROUP BY clause, you list the field names of the columns whose contents must be the same. You can only use the field names as they appear in the database table. Alias names from the SELECT clause are not allowed.
    All columns of the SELECT clause that are not listed in the GROUP BY clause must be included in aggregate functions. This defines how the contents of these columns is calculated when the lines are summarized.
    Specifying Columns Dynamically
    To specify the columns in the GROUP BY clause dynamically, use:
    ... GROUP BY (<itab>) ...
    where <itab> is an internal table with line type C and maximum length 72 characters containing the column names <s 1 > <s 2 > .....
    Example
    DATA: CARRID TYPE SFLIGHT-CARRID,
          MINIMUM TYPE P DECIMALS 2,
          MAXIMUM TYPE P DECIMALS 2.
    SELECT   CARRID MIN( PRICE ) MAX( PRICE )
    INTO     (CARRID, MINIMUM, MAXIMUM)
    FROM     SFLIGHT
    GROUP BY CARRID.
      WRITE: / CARRID, MINIMUM, MAXIMUM.
    ENDSELECT.
    regards
    vinod

  • How long should and Iphone 4S battery last using wifi continuously and having all notofocations and locations services ON and Off???

    1. Hi, How long should and Iphone 4S battery last using wifi continuously and having all notofocations and locations services ON and Off???
    2. What battery percentage should use if I do not make calls all day and wifi is on?
    3. What battery percentage should use if I do not make calls all day and wifi is off?
    4. If I do not have a Sim Card inside my Iphone 4S will the phone use more battery life?
    5. In what time should the iphone normally discharge?
    6. Basically how would i know if my battery is not defective as some people say?

    all your questions are relative to individual use, therefore nobody could give you any definitive answer to any of them.

  • Use of group by and having clause

    hi frnds
    can anybody explain me the use of group by an having clause in select state ment

    Hi Rohit,
    1. GROUP BY f1 ... fn
    2. GROUP BY (itab)
    1. GROUP BY f1 ... fn
    Effect
    Groups database table data in a SELECT command on one line in the result set. A group is a set of lines which all have the same values in each column determined by the field descriptors f1 ... fn.
    ... GROUP BY f1 ... fn always requires a list in the SELECT clause. If you use field descriptors without an aggregate funciton in the SELECT clause, you must list them in the GROUP BY f1 ... fn clause.
    Example
    Output the number of passengers, the total weight and the average weight of luggage for all Lufthansa flights on 28.02.1995:
    TABLES SBOOK.
    DATA:  COUNT TYPE I, SUM TYPE P DECIMALS 2, AVG TYPE F.
    DATA:  CONNID LIKE SBOOK-CONNID.
    SELECT CONNID COUNT( * ) SUM( LUGGWEIGHT ) AVG( LUGGWEIGHT )
           INTO (CONNID, COUNT, SUM, AVG)
           FROM SBOOK
           WHERE
             CARRID   = 'LH'       AND
             FLDATE   = '19950228'
           GROUP BY CONNID.
      WRITE: / CONNID, COUNT, SUM, AVG.
    ENDSELECT.
    Note
    ... GROUP BY f1 ... fn is not supported for pooled and cluster tables.
    2. GROUP BY (itab)
    Effect
    Works like GROUP BY f1 ... fn if the internal table itab contains the list f1 ... fn as ABAP source code. The internal table itab can only have one field. This field must be of the type C and should not be more than 72 characters long. itab must be enclosed in parentheses and there should be no blanks between the parentheses and the table name.
    Note
    The same restrictions apply to this variant as to GROUP BY f1 ... fn.
    Example
    Output all Lufthansa departure points with the number of destinations:
    TABLES: SPFLI.
    DATA:   BEGIN OF WA.
              INCLUDE STRUCTURE SPFLI.
    DATA:     COUNT TYPE I.
    DATA:   END OF WA.
    DATA:   WA_TAB(72) TYPE C,
            GTAB LIKE TABLE OF WA_TAB,
            FTAB LIKE TABLE OF WA_TAB,
            COUNT TYPE I.
    CLEAR: GTAB, FTAB.
    WA_TAB = 'COTYFROM COUNT( * ) AS COUNT'. APPEND FTAB.
    APPEND WA_TAB TO FTAB.
    WA_TAB = 'CITYFROM'.
    APPEND WA_TAB TO GTAB.
    SELECT DISTINCT (FTAB)
           INTO CORRESPONDING FIELDS OF WA
           FROM SPFLI
           WHERE
             CARRID   = 'LH'
           GROUP BY (GTAB).
      WRITE: / WA-CITYFROM, WA-COUNT.
    ENDSELECT.
    Regards,
    Susmitha

  • Where or Having clause and COUNT(1)

    I'm having trouble trying to figure out the way to get the conditional difference between two counts in a where clause.
    I would like to scan a table and only select records where the record count of one column attribute is different than another.
    I have
    select name, count(1) from skill <<< TOTAL_COUNT
    and
    select name, count(1) from skill where score is not NULL <<<< SCORED_COUNT
    I want to have a statement that just returns the names for those where TOTAL_COUNT - SCORED_COUNT = 0
    ... meaning those names where any of the rows have not been scored.
    I've tried a "having clause" but it still returns all there names. Even those there TOTAL_COUNT - SCORED_COUNT > 0
    Here's the non-working code....
    select * from
    (select full_name
    from emp e
    where e.manager = 'Smith, John'
    having
    ((select count(1)
    from emp_skill es
    where es.emp_fk = e.id
    group by null) -
    (select count(1)
    from emp_skill es1
    where es1.emp_fk = e.id and
    es1.self_prof is not NULL
    group by null)) = 0
    )

    Don't take 3360 too seriously in this context. COUNT(expression) is a bit of a running joke around these parts.
    However, his response does contain the seed of the solution for your problem.
    COUNT(<expression>) works because the COUNT function counts all rows with a non-null value for expression. So COUNT('Chocula') counts the non-null occurences of the literal string 'Chocula' in the table. Obviously, this counts every row in the table. COUNT(*) counts all the non-null occurences of a row in the table (even a row with all null values is a row). Clearly these are equivalent.
    However, if <expression> evaluates differently for each row, then COUNT(*) and COUNT(<expression>) can differ. So, for your example, assuming that the scored column is truly NULL in some records, what you need is something like:
    SQL> SELECT * FROM skill;
    NAME            SCORE
    BOB                 5
    BOB                 6
    BOB                 7
    BILL                5
    BILL                8
    BILL
    SQL> SELECT name, total, scored
      2  FROM (SELECT name, count(*) total, count(score) scored
      3        FROM skill
      4        GROUP BY name)
      5  WHERE total <> scored;
    NAME            TOTAL     SCORED
    BILL                3          2

  • How can I use a where in Select clause?

    How can I use a where in select clasue when the other part of the where I do not not.
    I mean that
    Select *
    from mara
    where MATNR = MT*
    That means it can have MTA, MTB, MTC....and so on
    I can I write this code.
    Regards,
    Subhasish

    hiii
    you can use following query
    SELECT * FORM mara WHERE matnr CONTAINING 'MT'
    or use following
    select * from mara WHERE matnr =  'MT%'
    reward if useful
    thx
    twinkal

  • Using column aliases in having clause error

    This is the query I'm trying to run.
    select concat(concat(student.last_name, ', '), student.first_name) student, count(school_apply.decision) decision
    from student, school_apply
    where student.student_id = school_apply.student_id
    and school_apply.decision = 'accepted'
    having decision < 3
    group by student.last_name, student.first_name
    order by count(school_apply.decision) desc, student.last_name, student.first_name;
    I got the following error
    Error at Command Line:5 Column:7
    Error report:
    SQL Error: ORA-00979: not a GROUP BY expression
    00979. 00000 - "not a GROUP BY expression"
    if in the having I use count(school_apply.decision) instead of the alias, it works fine. Why is this? and how can I use the alias'd column in the SQL?

    Hi,
    user4038196 wrote:
    This is the query I'm trying to run.
    select concat(concat(student.last_name, ', '), student.first_name) student, count(school_apply.decision) decision
    from student, school_apply
    where student.student_id = school_apply.student_id
    and school_apply.decision = 'accepted'
    having decision < 3
    group by student.last_name, student.first_name
    order by count(school_apply.decision) desc, student.last_name, student.first_name;
    I got the following error
    Error at Command Line:5 Column:7
    Error report:
    SQL Error: ORA-00979: not a GROUP BY expression
    00979. 00000 - "not a GROUP BY expression"
    if in the having I use count(school_apply.decision) instead of the alias, it works fine. Why is this? and how can I use the alias'd column in the SQL?When you define a column alias, like decision, in a query, you can use it in the ORDER BY clause. That's the only place in that query where you can use it.
    You can always assign the alias in a sub-query, then use it anywhere you want to in a super-query, like this:
    WITH     got_aggregates     AS
         select   student.last_name || ', '
                                  || student.first_name     AS student
         ,        count (school_apply.decision)           AS decision
         from       student
         ,       school_apply
         where        student.student_id     = school_apply.student_id
         and       school_apply.decision = 'accepted'
         group by  student.last_name
         ,            student.first_name
    SELECT    *
    FROM       got_aggregates
    WHERE       decision     < 3          -- Okay to use alias from sub-query
    ORDER BY  decision     DESC          -- Okay to use alias from sub-query
    ,            student               -- Okay to use alias from sub-query
    ;

  • Bin fitting with a counter using both analytics and model clause.

    11.2.0.3
    This falls under 'just want to figure out how to do it'. Its not critical for work. I want to try to see if its possible to do this with both analytic function and with a model clause. Just to see if its possible. It has been stumping me.
    I got the idea to look at this from this article about bin fitting. I have been playing with the model clause and I think you would do something with the 'increment' clause, but I dont see a way to reset it to 1 at a certain point.
    http://www.oracle.com/technetwork/issue-archive/2012/12-mar/o22asktom-1518271.html
    The case I want to look at is, bin fitting based on a counter and a partition by. In theory this should be simpler than the example in the link.
    [code]
    create table myrooms (
    room_number number,
    person_id        number);
    create unique index myrooms_ind on myrooms(room_number,person_id);
    [/code]
    Person_id is not unique. So row_number is more appropriate than rank or dense_rank.
    Problem: Partition by room_number, assign up to 50 people to a specific group with in the same room. This seems like it could be handled with a row_number() and a window clause, but that is not supported.
    I need to basically translate the old procedural counter into sql:
    pseudo-code that does not compile that would have a reason to use this logic.
    [code]
    declare
      cursor curGetRoom
         select room_number,person_id
            from my rooms
          order by room_number;
    counter number := 1;
    vCurrentRoom myroom.room_number%type;
    begin
        for i in curGetRoom loop
            if vCurrentRoom is null then
               vCurrentRoom := i.room_number;
            elsif vCurrentRoom = i.room_number then
                  if counter < 51 then counter :=counter+1;
                  else counter := 1;
            else
                 vCurrentRoom := i.room_number;
                counter :=1;
            end if;
    end;
    [/code]
    simple partition query., but I dont see a way to limit this to 50 and then start over. Window functions are not supported with row_number()
    [code]
    select room_number,person_id,row_number() over (partition by room_number order by person_id) rn
    from myrooms
    [/code]

    11.2.0.3
    This falls under 'just want to figure out how to do it'. Its not critical for work. I want to try to see if its possible to do this with both analytic function and with a model clause. Just to see if its possible. It has been stumping me.
    I got the idea to look at this from this article about bin fitting. I have been playing with the model clause and I think you would do something with the 'increment' clause, but I dont see a way to reset it to 1 at a certain point.
    http://www.oracle.com/technetwork/issue-archive/2012/12-mar/o22asktom-1518271.html
    The case I want to look at is, bin fitting based on a counter and a partition by. In theory this should be simpler than the example in the link.
    [code]
    create table myrooms (
    room_number number,
    person_id        number);
    create unique index myrooms_ind on myrooms(room_number,person_id);
    [/code]
    Person_id is not unique. So row_number is more appropriate than rank or dense_rank.
    Problem: Partition by room_number, assign up to 50 people to a specific group with in the same room. This seems like it could be handled with a row_number() and a window clause, but that is not supported.
    I need to basically translate the old procedural counter into sql:
    pseudo-code that does not compile that would have a reason to use this logic.
    [code]
    declare
      cursor curGetRoom
         select room_number,person_id
            from my rooms
          order by room_number;
    counter number := 1;
    vCurrentRoom myroom.room_number%type;
    begin
        for i in curGetRoom loop
            if vCurrentRoom is null then
               vCurrentRoom := i.room_number;
            elsif vCurrentRoom = i.room_number then
                  if counter < 51 then counter :=counter+1;
                  else counter := 1;
            else
                 vCurrentRoom := i.room_number;
                counter :=1;
            end if;
    end;
    [/code]
    simple partition query., but I dont see a way to limit this to 50 and then start over. Window functions are not supported with row_number()
    [code]
    select room_number,person_id,row_number() over (partition by room_number order by person_id) rn
    from myrooms
    [/code]

  • Simple Select query with 'where', 'and', 'between' clauses takes time

    Hi,
    I have a select query as below
    SELECT * FROM (SELECT a.*,ROWNUM currentStartRecord From (select ai_inbound.ai_inb_seq tableseq,'AI_INBOUND' tablename,'INBOUND' direction,ai_inbound.appl,ai_inbound.ai_date datetime,ai_inbound.ic_receiver_id pg_id,ai_inbound.ic_sender_id tp_id,ai_inbound.session_no,ai_inbound.ic_ctl_no,ai_inbound.msg_set_id msg_type,ai_inbound.appl_msg_ctl_no reference_no,ai_inbound.fg_version version,ai_inbound.msg_status status,ai_inbound.input_file_name,ai_inbound.output_file_name,ai_inbound.ack_file_name from ai_inbound where ai_inbound.appl = ? and ai_inbound.ai_date between ? and ? )a where ROWNUM <= 49)where currentStartRecord >= 0
    The above query takes longer time through application than expected when the date fields are passed whereas it works fine when no date fields are passed. We are using oracle9.2 version of the database. All the indexed columns and partitioned indexed columns are rebuild.
    Kindly let me know how can i tune up the query to improve the performance.
    Thanks

    Hi,
    I have a select query as below
    SELECT * FROM (SELECT a.*,ROWNUM currentStartRecord From (select ai_inbound.ai_inb_seq tableseq,'AI_INBOUND' tablename,'INBOUND' direction,ai_inbound.appl,ai_inbound.ai_date datetime,ai_inbound.ic_receiver_id pg_id,ai_inbound.ic_sender_id tp_id,ai_inbound.session_no,ai_inbound.ic_ctl_no,ai_inbound.msg_set_id msg_type,ai_inbound.appl_msg_ctl_no reference_no,ai_inbound.fg_version version,ai_inbound.msg_status status,ai_inbound.input_file_name,ai_inbound.output_file_name,ai_inbound.ack_file_name from ai_inbound where ai_inbound.appl = ? and ai_inbound.ai_date between ? and ? )a where ROWNUM <= 49)where currentStartRecord >= 0
    The above query takes longer time through application than expected when the date fields are passed whereas it works fine when no date fields are passed. We are using oracle9.2 version of the database. All the indexed columns and partitioned indexed columns are rebuild.
    Kindly let me know how can i tune up the query to improve the performance.
    Thanks

  • Is anyone using VMware fusion and having trouble with USB devices not being recognised

    I have an Terratec Axon AX50 Guitar to Midi interface. The editor software is not Lion compatible so I have attempted to run that bit in Windows 7 on a virtual machine.
    The problem is that the VM machine will not recognise the USB device, even though when it asks which machine I want to connect to it names the device correctly.
    Any Ideas ?

    Device not recognized by iTune
    http://support.apple.com/kb/TS1591

  • Question about GROUP BY and HAVING

    Good afternoon,
    I have the following query which returns the desired result (set of students who take CS112 or CS114 but not both). I wanted to "condense" it into a single SELECT statement (if that is at all possible - DDL to execute the statement is provided at the end of this post):
    -- is this select distinct * and its associated where clause absolutely
    -- necessary to obtain the result ?
    select distinct *
      from (
            select s.sno,
                   s.sname,
                   s.age,
                   sum(case when t.cno in ('CS112', 'CS114')
                            then 1
                            else 0
                       end)
                     over (partition by s.sno) as takes_either_or_both
              from student s join take t
                               on (s.sno = t.sno)
      where takes_either_or_both = 1
    ;The following looked reasonable but, unfortunately unsuccessful:
      Window functions not allowed here (in Having Clause)
    select max(s.sno),
           max(s.sname),
           max(s.age),
           sum(case when t.cno in ('CS112', 'CS114')
                    then 1
                    else 0
               end)
             over (partition by s.sno) as takes_either_or_both
      from student s join take t
                       on (s.sno = t.sno)
    group by s.sno
    having sum(case when t.cno in ('CS112', 'CS114')
                    then 1
                    else 0
               end)
             over (partition by s.sno) = 1
    Invalid identifier in Having clause
    select s.sno,
           s.sname,
           s.age,
           sum(case when t.cno in ('CS112', 'CS114')
                    then 1
                    else 0
               end)
             over (partition by s.sno) as takes_either_or_both
      from student s join take t
                       on (s.sno = t.sno)
    group by s.sno, s.sname, s.age
    having takes_either_or_both = 1
    ;I have searched for a document that completely defines the sequence in which the clauses are executed. I have found tidbits here and there but not something complete. I realize that my running into problems like this one is due to my lack of understanding of the sequence and the scope of the clauses that make up a statement. Because of this, I cannot even tell if it is possible to write the above query using a single select statement. Pardon my bit of frustration...
    Thank you for your help,
    John.
    DDL follows.
            /* drop any preexisting tables */
            drop table student;
            drop table courses;
            drop table take;
            /* table of students */
            create table student
            ( sno integer,
              sname varchar(10),
              age integer
            /* table of courses */
            create table courses
            ( cno varchar(5),
              title varchar(10),
              credits integer
            /* table of students and the courses they take */
            create table take
            ( sno integer,
              cno varchar(5)
            insert into student values (1,'AARON',20);
            insert into student values (2,'CHUCK',21);
            insert into student values (3,'DOUG',20);
            insert into student values (4,'MAGGIE',19);
            insert into student values (5,'STEVE',22);
            insert into student values (6,'JING',18);
            insert into student values (7,'BRIAN',21);
            insert into student values (8,'KAY',20);
            insert into student values (9,'GILLIAN',20);
            insert into student values (10,'CHAD',21);
            insert into courses values ('CS112','PHYSICS',4);
            insert into courses values ('CS113','CALCULUS',4);
            insert into courses values ('CS114','HISTORY',4);
            insert into take values (1,'CS112');
            insert into take values (1,'CS113');
            insert into take values (1,'CS114');
            insert into take values (2,'CS112');
            insert into take values (3,'CS112');
            insert into take values (3,'CS114');
            insert into take values (4,'CS112');
            insert into take values (4,'CS113');
            insert into take values (5,'CS113');
            insert into take values (6,'CS113');
            insert into take values (6,'CS114');

    Hi, John,
    Just use the aggregate SUM function.
            select s.sno,
                   s.sname,
                   s.age,
                   sum(case when t.cno in ('CS112', 'CS114')
                            then 1
                            else 0
                       end) as takes_either_or_both
              from student s join take t
                               on (s.sno = t.sno)
           GROUP BY  s.sno,
                    s.sname,
                  s.age
           HAVING  sum(case when t.cno in ('CS112', 'CS114')
                            then 1
                            else 0
                       end)  = 1;Analytic functions are computed after the WHERE- and HAVING clause have been applied. To use the results of an analytic fucntion in a WHERE- or HAVING clause, you have to compute it in a sub-query, and then you can use it in a WHERE- or HAVING clause of a super-query.

  • Use CASE in HAVING clause

    I feel like this should be simple but it I'm just not grasping it. 
    Say I have this query:
    SELECT order_number, order_date FROM orders
    I basically want to pull any order from the last 24 hours.  Well this is fairly easy for Tue-Fri but when I run the query on Mon, it will have zero results since there are no orders from the weekend.  If the query is ran on Mon it should query
    Fri instead.
    I'm attempting to use case in my having clause but no luck. 
    HAVING (DATEDIFF(dd, GETDATE(), order_date = (CASE order_date WHEN DATENAME(weekday,getdate()) = 'Friday' THEN '3' ELSE '0' END)
    Sure my syntax or parentheses is way off, any help is appreciated.  Thanks.

    Check out the following CASE expression:
    SELECT CASE WHEN datename(dw,getdate()) = 'Monday' THEN
    CONVERT(DATE,(SELECT dateadd(d, -((datepart(weekday, getdate()) + 1 + @@DATEFIRST) % 7), getdate())))
    ELSE CONVERT(DATE, DATEADD(dd, -1, getdate())) END;
    /********* TEST ****************/
    DECLARE @Dt datetime;
    DECLARE @i int = 0; WHILE (@i < 10) BEGIN
    SET @Dt = dateadd(dd, @i, getdate());
    SELECT Today = @Dt, WeekDay=DATENAME(dw,@Dt), PrevBusinessDay= CASE WHEN datename(dw,@Dt) = 'Monday' THEN
    CONVERT(DATE, (SELECT dateadd(d, -((datepart(weekday, @Dt) + 1 + @@DATEFIRST) % 7), @Dt)))
    ELSE CONVERT(DATE, DATEADD(dd, -1, @Dt)) END;
    SET @i += 1; END -- WHILE
    Today WeekDay PrevBusinessDay
    2014-06-20 19:46:45.130 Friday 2014-06-19
    Today WeekDay PrevBusinessDay
    2014-06-23 19:49:04.817 Monday 2014-06-20
    Today WeekDay PrevBusinessDay
    2014-06-24 19:46:45.130 Tuesday 2014-06-23
    Today WeekDay PrevBusinessDay
    2014-06-25 19:46:45.130 Wednesday 2014-06-24
    Today WeekDay PrevBusinessDay
    2014-06-26 19:46:45.130 Thursday 2014-06-25
    Today WeekDay PrevBusinessDay
    2014-06-27 19:46:45.130 Friday 2014-06-26
    Datetime functions:  
    http://www.sqlusa.com/bestpractices/datetimeconversion/
    Consider also implementation with a calendar table.
    Kalman Toth Database & OLAP Architect
    SQL Server 2014 Design & Programming
    New Book / Kindle: Exam 70-461 Bootcamp: Querying Microsoft SQL Server 2012

  • Can we use multiset and with clause both

    Please let me know how to use both multiset and with clause.

    You need one more inlining, as e.g. in:
    SQL> select *
    from table (cast (multiset (select *
                                from (with t as (select deptno from dept)
                                      select * from t)) as sys.dbms_debug_vc2coll))
    COLUMN_VALUE                           
    10                                     
    20                                     
    30                                     
    40                                     
    50                                     
    5 rows selected.

  • Execution of subquery of IN and EXISTS clause.

    Hi Friends,
    Suppose we have following two tables:
    emp
    empno number
    ename varchar2(100)
    deptno number
    salary number
    dept
    deptno number
    location varchar2(100)
    deptname varchar2(100)
    status varchar2(100)
    Where dept is the master table for emp.
    Following query is fine to me:
    SELECT empno, ename
    FROM emp,dept
    WHERE emp.deptno = dept.deptno
    AND emp.salary &gt;=5000
    AND dept.status = 'ACTIVE';
    But I want to understand the behaviour of inline query (Used with IN and EXISTS clause) for which I have used this tables as an example (Just as Demo).
    1)
    Suppose we rewrite the above query as following:
    SELECT empno, ename
    FROM emp
    WHERE emp.salary &gt;=5000
    AND deptno in (SELECT deptno FROM dept where status = 'ACTIVE')
    Question: as shown in above query, suppose in our where clause, we have a condition with IN construct whose subquery is independent (it is not using any column of master query's resultset.). Then, will that query be executed only once or will it be executed for N number of times (N= number of records in emp table)
    In other words, how may times the subquery of IN clause as in above query be executed by complier to prepared the subquery's resultset?
    2)
    Suppose the we use the EXISTS clause (or NOT EXISTS clause) with subquery where, the subquery uses the field of master query in its where clause.
    SELECT E.empno, E.ename
    FROM emp E
    WHERE E.salary &gt;=5000
    AND EXISTS (SELECT 'X' FROM dept D where status = 'ACTIVE' AND D.deptno = E.deptno)
    Here also, I got same confusion. For how many times the subquery for EXISTS will be executed by oracle. For one time or for N number of times (I think, it will be N number of times).
    3)
    I know we can't define any fix thumbrule and its highly depends on requirement and other factors, but in general, Suppose our main query is on heavily loaded large transaction table and need to check existance of record in some less loaded and somewhat smaller transaction table, than which way will be better from performance point of view from above three. (1. Use of JOIN, 2. Use of IN, 3. Use of EXISTS)
    Please help me get solutions to these confusions..
    Thanks and Regards,
    Dipali..

    Dipali,
    First, I posted the links with my name only, I don;t know how did you pick another handle for addressing it?Never mind that.
    >
    Now another confusion I got.. I read that even if we used EXISTS and , CBO feels (from statistics and all his analysis) that using IN would be more efficient, than it will rewrite the query. My confusion is that, If CBO is smart enough to rewrite the query in its most efficient form, Is there any scope/need for a Developer/DBA to do SQL/Query tuning? Does this means that now , developer need not to work hard to write query in best menner, instade just what he needs to do is to write the query which resluts the data required by him..? Does this now mean that now no eperts are required for SQL tuning?
    >
    Where did you read that?Its good to see the reference which says this.I haven't come across any such thing where CBO will rewrite the query like this. Have a look at the following query.What we want to do is to get the list of all teh departments which have atleast one employee working in it.So how would be we write this query? Theremay be many ways.One,out of them is to use distinct.Let's see how it works,
    SQL> select * from V$version;
    BANNER
    Oracle Database 11g Enterprise Edition Release 11.1.0.6.0 - Production
    PL/SQL Release 11.1.0.6.0 - Production
    CORE    11.1.0.6.0      Production
    TNS for 32-bit Windows: Version 11.1.0.6.0 - Production
    NLSRTL Version 11.1.0.6.0 - Production
    SQL> set timing on
    SQL> set autot trace exp
    SQL> SELECT distinct  D.deptno, D.dname
      2        FROM     scott.dept D,scott.emp E
      3  where e.deptno=d.deptno
      4  order by d.deptno;
    Elapsed: 00:00:00.12
    Execution Plan
    Plan hash value: 925733878
    | Id  | Operation                     | Name    | Rows  | Bytes | Cost (%CPU)| T
    ime     |
    |   0 | SELECT STATEMENT              |         |     9 |   144 |     7  (29)| 0
    0:00:01 |
    |   1 |  SORT UNIQUE                  |         |     9 |   144 |     7  (29)| 0
    0:00:01 |
    |   2 |   MERGE JOIN                  |         |    14 |   224 |     6  (17)| 0
    0:00:01 |
    |   3 |    TABLE ACCESS BY INDEX ROWID| DEPT    |     4 |    52 |     2   (0)| 0
    0:00:01 |
    |   4 |     INDEX FULL SCAN           | PK_DEPT |     4 |       |     1   (0)| 0
    0:00:01 |
    |*  5 |    SORT JOIN                  |         |    14 |    42 |     4  (25)| 0
    0:00:01 |
    |   6 |     TABLE ACCESS FULL         | EMP     |    14 |    42 |     3   (0)| 0
    0:00:01 |
    Predicate Information (identified by operation id):
       5 - access("E"."DEPTNO"="D"."DEPTNO")
           filter("E"."DEPTNO"="D"."DEPTNO")
    SQL>
    SQL> SELECT distinct  D.deptno, D.dname
      2        FROM     scott.dept D,scott.emp E
      3  where e.deptno=d.deptno
      4  order by d.deptno;
        DEPTNO DNAME
            10 ACCOUNTING
            20 RESEARCH
            30 SALES
    Elapsed: 00:00:00.04
    SQL>So CBO did what we asked it do so.It made a full sort merge join.Now there is nothing wrong in it.There is no intelligence added by CBO to it.So now what, the query looks okay isn't it.If the answer is yes than let's finish the talk here.If no than we proceed further.
    We deliberately used the term "atleast" here.This would govern that we are not looking for entirely matching both the sources, emp and dept.Any matching result should solve our query's result.So , with "our knowledge" , we know that Exist can do that.Let's write teh query by it and see,
    SQL> SELECT   D.deptno, D.dname
      2        FROM     scott.dept D
      3          WHERE    EXISTS
      4                 (SELECT 1
      5                  FROM   scott.emp E
      6                  WHERE  E.deptno = D.deptno)
      7        ORDER BY D.deptno;
        DEPTNO DNAME
            10 ACCOUNTING
            20 RESEARCH
            30 SALES
    Elapsed: 00:00:00.00
    SQL>Wow, that's same but there is a small difference in the timing.Note that I did run the query several times to elliminate the physical reads and recursive calls to effect the demo. So its the same result, let's see the plan.
    SQL> SELECT   D.deptno, D.dname
      2        FROM     scott.dept D
      3          WHERE    EXISTS
      4                 (SELECT 1
      5                  FROM   scott.emp E
      6                  WHERE  E.deptno = D.deptno)
      7        ORDER BY D.deptno;
    Elapsed: 00:00:00.00
    Execution Plan
    Plan hash value: 1090737117
    | Id  | Operation                    | Name    | Rows  | Bytes | Cost (%CPU)| Ti
    me     |
    |   0 | SELECT STATEMENT             |         |     3 |    48 |     6  (17)| 00
    :00:01 |
    |   1 |  MERGE JOIN SEMI             |         |     3 |    48 |     6  (17)| 00
    :00:01 |
    |   2 |   TABLE ACCESS BY INDEX ROWID| DEPT    |     4 |    52 |     2   (0)| 00
    :00:01 |
    |   3 |    INDEX FULL SCAN           | PK_DEPT |     4 |       |     1   (0)| 00
    :00:01 |
    |*  4 |   SORT UNIQUE                |         |    14 |    42 |     4  (25)| 00
    :00:01 |
    |   5 |    TABLE ACCESS FULL         | EMP     |    14 |    42 |     3   (0)| 00
    :00:01 |
    Predicate Information (identified by operation id):
       4 - access("E"."DEPTNO"="D"."DEPTNO")
           filter("E"."DEPTNO"="D"."DEPTNO")Can you see a keyword called Semi here? This means that Oralce did make an equi join but not complete.Compare the bytes/rows returned from this as well as cost with the first query.Can you notice the difference?
    So what do we get from all this?You asked that if CBO becomes so smart, won't we need developers/dbas at that time?The answer is , what one wants to be, a monkey or an astranaut? Confused,read this,
    http://www.method-r.com/downloads/doc_download/6-the-oracle-advisors-from-a-different-perspective-karen-morton
    So it won't matter how much CBO would become intelligent, there will be still limitations to where it can go, what it can do.There will always be a need for a human to look all the automations.Rememember even the most sofisticated system needs some button to be pressed to get it on which is done by a human hand's finger ;-).
    Happy new year!
    HTH
    Aman....

Maybe you are looking for