1

I have the following code and I would like to remove the top 5% of the records for the Triage_To_Dr_Sees_Adjust numeric variable. Is this possible(I know using Select TOP(95) Percent would give me the top 95% but I want reverse of that, I would like the bottom 95%)?. Thank you!

UPDATE: I included code from an answer below, now my issue is that this code produces no records.

use EMTCQIData

DECLARE @StartDate Date
DECLARE @EndDate Date

Set @StartDate = '05/01/2017'
Set @EndDate = '12/31/2018'


SELECT sub.*
    FROM (
    Select *,
    Format([CHECKIN_DATE_TIME],'dddd') AS Checkin_Day,  
    CONVERT(VARCHAR(10),[CHECKIN_DATE_TIME],111) as Checkin_date, 
    CONVERT(VARCHAR(20),[CHECKIN_DATE_TIME],108) as Checkin_Time, 
    Case when TRIAGE_TO_DR_SEES < 0 then 0 else TRIAGE_TO_DR_SEES end as 
    TRIAGE_TO_DR_SEES_ADJUST 
    FROM ED_TAT_MASTER
    WHERE 
    (CHECKIN_DATE_TIME > @StartDate and CHECKIN_DATE_TIME < @EndDate) 
    AND (TRIAGE_DATE_TIME not like '')
    AND (TRIAGE_TO_DR_SEES not like '%no%')
    AND (TRACK_GROUP='ED Tracking Group') 
    AND (FORMAT([CHECKIN_DATE_TIME], 'dddd') = 'Sunday') 
    AND CHECKIN_DATE_TIME not like '%2017-07-02%' 
    AND CHECKIN_DATE_TIME not like '%2017-12-24%'
    AND CHECKIN_DATE_TIME not like '%2018-06-10%'
) sub

WHERE sub.TRIAGE_TO_DR_SEES not in (select top(5) Percent sub.TRIAGE_TO_DR_SEES
FROM ED_TAT_MASTER
ORDER BY CHECKIN_DATE_TIME)
7
  • 3
    Why not use TOP (5) PERCENT and switch the direction of your ORDER BY? The "last" 5 percent of records in one direction is the first in the other.
    – Thom A
    Commented Feb 21, 2019 at 18:38
  • 3
    "I would like the bottom 95%" ... the "bottom" 95% is just the top 95% in reverse order. Commented Feb 21, 2019 at 18:51
  • 1
    Personally, I would go with my answer. I feel that that IN could be expensive (you'll need to do 2 scans of the table), and this seems harder to read.
    – Thom A
    Commented Feb 21, 2019 at 21:59
  • 1
    What bit is it you're struggling with @Greg? The subquery or the outer query? At the end of the day, the query is simple SELECT * FROM (SELECT TOP (95) PERCENT * FROM [Table] ORDER BY ID DESC) ORDER BY ID ASC; I don't mean to be rude, but I'm not sure what part of that is difficult to understand there.
    – Thom A
    Commented Feb 22, 2019 at 14:15
  • 1
    You don't need to WITH. That was just me generating sample data. I'll update the query a bit for you.
    – Thom A
    Commented Feb 22, 2019 at 15:51

2 Answers 2

7

This gets the top 5 percent in a subquery, then gets everything else in the main query. So add your logic for the 5% in the subquery, then the outer query will get you everything else.

SELECT *
FROM TableName
WHERE TableIdentity NOT IN (
    SELECT TOP (5) PERCENT TableIdentity
    FROM TableName
    ORDER BY TableIdentity (OR whatever logic you want)
)
4
  • thank you! For some reason, I'm having an issue embedding this code within my preexisting code as I'm not seeing any records removed. I updated my code above to reflect your answer. I suspect I'm making a stupid mistake.
    – Raven
    Commented Feb 21, 2019 at 19:17
  • 1
    Do you want your where logic applied to top 5% as well, if so need that in the subquery as well. But main issue is you are using OR after the subquery and that is the issue. You are saying NOT top 5% OR the other logic. So make that AND.
    – Brad
    Commented Feb 21, 2019 at 19:23
  • I would like my preexisting WHERE logic to be applied first. Then, I would like to take out the top 5% of TRIAGE_TO_DR_SEES times. This is also something I'm struggling with. Apologies for my lack of clarity.
    – Raven
    Commented Feb 21, 2019 at 19:27
  • I am now having issues after writing the subquery-see updated question above. The subquery produces no records (I do not get an error) it's just all of the records are blank.
    – Raven
    Commented Feb 21, 2019 at 21:56
4

As mentioned in the comments, the "last" 95 percent is just the "first" 95 percent the other way, so just reverse your ORDER BY. If the "final" order of your data is that important, then you can wrap it in a subquery:

--Generate some sample data (numbers 1 to 1000)
WITH N AS (
    SELECT N
    FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))V(N)),
Tally AS(
    SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS I
    FROM N N1
         CROSS JOIN N N2
         CROSS JOIN N N3)
--The solution
SELECT I
FROM (SELECT TOP (95) PERCENT I
      FROM Tally
      ORDER BY I DESC) T
ORDER BY I ASC;

This returns the numbers 51-1000 in numerical order, aka the "last" 95%.

So, for your query, in Pseudo-SQL, it'll be:

SELECT {YourColumns}
FROM (SELECT TOP (95) PERCENT
             {YourColumns},
             CHECKIN_DATE_TIME
      FROM ED_TAT_MASTER
      WHERE ...
      ORDER BY CHECKIN_DATE_TIME DESC --The reverse of the order you want
      ) AS T
ORDER BY CHECKIN_DATE_TIME ASC;
4
  • 1
    Not only is this a lot easier to understand it works in all situations.
    – Sean Lange
    Commented Feb 21, 2019 at 21:39
  • @Larnu Thank you! This code runs but it's still returning the top 95% of my values, the variable I'm attempting to remove the top 5% of values from is TRIAGE_TO_DR_SEES.
    – Raven
    Commented Feb 22, 2019 at 16:39
  • 1
    Then you need to change the column in the ORDER BY @Greg. I can't really explain anymore than I have. If you don't understand the SQL you shouldn't be using it (it's you who needs to support it, not I or anyone else on Stack Overflow); but if you don't understand it then you need to start learning SQL. ORDER BY is one of the basic operators in SQL. I suggest have a google of some online tutorials or maybe signing up to a course. Good luck!
    – Thom A
    Commented Feb 22, 2019 at 16:41
  • @Larnu, thanks! The data generated code removes the bottom 5% of my values (keeps top 95%). If I have values 1-1000, I want to remove anything greater than 950. The code your provided above removed 1-50 and then flipped the order of 51-950.
    – Raven
    Commented Feb 22, 2019 at 17:02

Not the answer you're looking for? Browse other questions tagged or ask your own question.