locked
Write query efficiently RRS feed

  • Question

  • Hi I am working out a query where it has to exclude records based on certain criteria. For instance in the following code I will have to exclude all the Customers who had only "No Show" for the Event and the venue is "USA".

    For instance ID 5, 6, 10. Can do it in 1 query rather than use an "Union" with 2 different queries. Please see code below.

    DECLARE @Event TABLE
    (ID INT
     , [Event] VARCHAR(100)
     , venue VARCHAR(100))
    INSERT INTO @Event
    SELECT 1, 'No Show', 'USA'
    UNION 
    SELECT 1, 'Labor Day', 'USA'
    UNION 
    SELECT 2, 'No Show', 'USA'
    UNION
    SELECT 2, 'Halloween', 'USA'
    UNION
    SELECT 3, 'No Show', 'CANADA'
    UNION
    SELECT 3, 'New Year Eve', 'CANADA'
    UNION
    SELECT 3, 'xmas', 'CANADA'
    UNION
    SELECT 4, 'July 4th', 'USA'
    UNION 
    SELECT 4, 'No Show', 'USA'
    UNION
    SELECT 4, 'Presidents day', 'USA'
    UNION
    SELECT 5, 'No Show', 'USA'
    UNION
    SELECT 6, 'No Show', 'USA'
    UNION
    SELECT 7, 'No Show', 'CANADA'
    UNION
    SELECT 7, 'No Show', 'MEXICO'
    UNION
    SELECT 8, 'No Show', 'UK'
    UNION
    SELECT 9, 'No Show', 'CHINA'
    UNION
    SELECT 10, 'No Show', 'USA'
    --SELECT *
    --FROM @Event
    ; WITH cte AS
     (
    SELECT ID, [Event], venue, DENSE_RANK() OVER(PARTITION BY ID ORDER BY CASE WHEN [Event] = 'No Show' THEN  2 ELSE 1 END, [Event]) AS Rnk 
    FROM @Event 
    WHERE venue = 'USA'
     )
    SELECT ID, [Event], venue FROM cte 
    WHERE ([Event] <> 'No Show' OR Rnk <> 1)
    UNION ALL
    SELECT ID, [Event], venue
    FROM @Event
    WHERE venue <> 'USA'
    Thanks.............
    Friday, October 26, 2012 2:42 PM

Answers

  • ; WITH cte AS
     (
    SELECT ID, [Event], venue, Count(ID) OVER(PARTITION BY ID) AS Rnk 
    FROM @Event 
     )
    SELECT ID, [Event], venue FROM cte 
    WHERE ((([Event] = 'No Show' AND Rnk > 1) or [Event] <> 'No Show')  
    AND venue = 'USA' ) 
    Or venue <> 'USA'
    Order by ID

    Friday, October 26, 2012 3:10 PM

All replies

  • Use GROUP BY and MAX and MIN to accomplish this -- somewhat similar to "relational division".  Perhaps something like this:

    select
      id,
      venue
    from @event
    where venue = 'USA'
      and event <> 'No Show'
    group by id, venue;
    /* -------- Output: --------
    id          venue
    ----------- ------
    1           USA
    2           USA
    4           USA
    */

    After seconds I thought the query above would cover it without the use of any aggregate functions.

    • Edited by Kent Waldrop Friday, October 26, 2012 4:22 PM
    • Proposed as answer by Breanch Monday, October 29, 2012 6:47 AM
    Friday, October 26, 2012 2:57 PM
  • ; WITH cte AS
     (
    SELECT ID, [Event], venue, Count(ID) OVER(PARTITION BY ID) AS Rnk 
    FROM @Event 
     )
    SELECT ID, [Event], venue FROM cte 
    WHERE ((([Event] = 'No Show' AND Rnk > 1) or [Event] <> 'No Show')  
    AND venue = 'USA' ) 
    Or venue <> 'USA'
    Order by ID

    Friday, October 26, 2012 3:10 PM
  • Try:

    DECLARE @Event TABLE
    (ID INT
     , [Event] VARCHAR(100)
     , venue VARCHAR(100))
    INSERT INTO @Event
    SELECT 1, 'No Show', 'USA'
    UNION 
    SELECT 1, 'Labor Day', 'USA'
    UNION 
    SELECT 2, 'No Show', 'USA'
    UNION
    SELECT 2, 'Halloween', 'USA'
    UNION
    SELECT 3, 'No Show', 'CANADA'
    UNION
    SELECT 3, 'New Year Eve', 'CANADA'
    UNION
    SELECT 3, 'xmas', 'CANADA'
    UNION
    SELECT 4, 'July 4th', 'USA'
    UNION 
    SELECT 4, 'No Show', 'USA'
    UNION
    SELECT 4, 'Presidents day', 'USA'
    UNION
    SELECT 5, 'No Show', 'USA'
    UNION
    SELECT 6, 'No Show', 'USA'
    UNION
    SELECT 7, 'No Show', 'CANADA'
    UNION
    SELECT 7, 'No Show', 'MEXICO'
    UNION
    SELECT 8, 'No Show', 'UK'
    UNION
    SELECT 9, 'No Show', 'CHINA'
    UNION
    SELECT 10, 'No Show', 'USA'
    
    
    
    ;WITH CTE
    AS
    (
     SELECT ID, [Event], Venue, DENSE_RANK() OVER (PARTITION BY ID ORDER BY [Event], Venue)Dr
     FROM @Event
    ),
    CTE2
    AS
    (
      SELECT ID, [Event], Venue, MAX(Dr) OVER (PARTITION BY ID)MxDr
      FROM CTE
    )
    
    SELECT ID, Event, venue 
    FROM CTE2
    WHERE 1 = CASE WHEN MxDr = 1 AND Event = 'No Show' AND venue = 'USA' THEN 0 
    			   ELSE 1 END
    ORDER BY 1			   


    Please mark as answer if this answers your question. Please mark as helpful if you found this post was helpful.



    Friday, October 26, 2012 7:18 PM
  • Please try below.

    select * from @Event
    where ID not in (select ID from @event where Event = 'No Show' and venue = 'USA'
    and ID not in (select ID from @Event where event <> 'No Show'))


    ESHANI. Please click "Mark As Answer" if a post solves your problem or "Vote As Helpful" if a post has been useful to you

    Monday, October 29, 2012 12:08 AM
  • Hi, Please execute below query simply:

    select  id,  venue  from @event 
    where venue = 'USA'  and event <> 'No Show'  
    group by id, venue;

    Ahsan Kabir
    Please remember to click Mark as Answer and Vote as Helpful on posts that help you.
    This can be beneficial to other community members reading the thread.
    http://www.aktechforum.blogspot.com/

    • Edited by Ahsan KabirMVP Monday, October 29, 2012 6:25 AM
    • Proposed as answer by Breanch Monday, October 29, 2012 6:47 AM
    Monday, October 29, 2012 5:01 AM
  • May be this will do :

    select ID FROM @Event
    WHERE Venue = 'USA'
    Group BY ID  
    HAVING MIN(Event) = MAX(Event)


    Thanks and regards, Rishabh K

    Monday, October 29, 2012 5:57 AM