Select statement with a condition on multiple entries - sql

Following is my table:
I want to create a view with the following conditions in a select statement:
If count(employee_id) > 1 then only the record having status = 'Current' is picked in the view.
I tried:
select employee_id
, case when COUNT(employee_id) > 1 and statusval = 'Current' then 'Y' else 'N' end as val
from table1
group by employee_id
I hope someone can help me with this statement. Thanks.

Try this
DECLARE #T TABLE (ID INT, STATUS VARCHAR(50))
INSERT INTO #T VALUES (1,'Current'),(2,'Historical'),(2,'Historical'),(2,'Current')
SELECT * FROM #T M
INNER JOIN (SELECT ID FROM #T
GROUP BY ID
HAVING COUNT(ID) > 1) S ON S.ID=M.ID
WHERE M.STATUS = 'Current'

Just to show you how your attempt could have looked. You were nearly there, you just needed to use the windowed version of count e.g.
with cte as (
select Employee_Id, [Status]
, case when count(*) over (partition by id) > 1 and [Status] = 'Current' then 1 else 0 end Val
from Table1
)
select Employee_Id, [Status]
from cte
where Val = 1;
And this approach appears on the face of it to perform better than a join.

All of your sample data have exactly one row with 'Current'. So, the simplest solution appears to be:
select t.*
from t
where t.status = 'Current';

Related

GoogleSQL - SELECT IF

I'm working with a dataset - structured like this
I want to exclude all records with ReviewRound being "a" if they have gone through review round "b" - If a set of unique ID's has an associated round "b" review, the round "a" review should not be included.
Some records have not gone to round "b". The issues I'm running into are as a result of there being multiple records for each unique ID.
Ideally this could be done in GoogleBigQuery, if not, filtering through GoogleScripts may also be an option!
Any suggestions would be appreciated!
If a set of unique ID's has an associated round "b" review, the round "a" review should not be included.
If I followed you correctly, you could express this as a not condition with a correlated subquery that ensures that, if the current record has ReviewRound = 'a', there is no other record that has the same id and ReviewRound = 'b'.
select t.*
from mytable t
where not (
t.ReviewRound = 'a'
and exists (
select 1
from mytable t1
and t1.id = t.id and t1.ReviewRound = 'b'
)
)
You can do this with window functions as well:
select t.* except (num_bs)
from (select t.*,
countif(reviewround = 'b') over (partition by id) as num_bs
from t
) t
where num_bs = 0 or reviewround = 'b';
By using window functions, you can solve it with this query
SELECT ID, Score
FROM (
SELECT *,
MAX(CASE WHEN ReviewRound = 'b' THEN 1 ELSE 0 END) OVER (partition by ID) as has_b
FROM mytable
) t
WHERE has_b = 0
Re-conceptualizing as keeping only the latest review round, I would try:
select * from mytable join
(select ID, max(ReviewRound) as ReviewRound from mytable group by ID)
on (ID, ReviewRound)

Count based on group with filter

I have a query that displays 2 columns: "Device_ID" and "Status". Device_ID is the name of all computers and status contains either "reboot" or "success" as values. I would like a third column that would count how many "success" there are for that specific Device_ID.
How could I go about doing this?
SELECT tgt.Device_ID, tgt.Status, src.cnt
FROM [TableName] tgt
INNER JOIN
(
Select Device_ID, count(CASE WHEN Status = 'SUCCESS' THEN 1 ELSE 0END) cnt
from [TableName]
GROUP BY Device_ID
) src
ON tgt.Device_ID= src.Device_ID;
SELECT A.Device_ID,A.Status,B.Count_of_Success_per_Device_ID
FROM Yourtable A
INNER JOIN
(
SELECT Device_ID,
SUM( CASE WHEN Status = 'Success' THEN 1 ELSE 0 END ) AS Count_of_Success_per_Device_ID
FROM Yourtable
GROUP BY Device_ID
) B
ON A.Device_ID = B.Device_ID ;

How to Always select a certain value 1st sql

say i have a TABLE with the values
1,2,2,3,4 and ALL
in the SAME column
and I then
SELECT DISTINCT
value
FROM table
How would I go about always selecting 'All' 1st ?
or atleast ordering it that 'All' is 1st.
NOTE: The column is a VARCHAR(x)
EDIT:
SELECT DISTINCT
Strategy
FROM #Strategy
ORDER BY case when Strategy = 'All' then 0 else 1 end,
Strategy DESC
This is my query currently
You chose correct keyword (DISTINCT) and correct expression (ORDER BY CASE WHEN ... END) for each individual question. The trick is to solve the questions one by one instead of once.
SELECT *
FROM
(
SELECT DISTINCT T1.*
FROM (VALUES ('1'), ('2'), ('2'), ('3'), ('4'), ('ALL')) AS T1(Strategy)
) AS T2
ORDER BY CASE WHEN Strategy = 'ALL' THEN 0 ELSE 1 END, Strategy;
In this instance just use:
SELECT DISTINCT Value FROM TABLE ORDER BY Value Desc
Please try this.
Declare #table table (id varchar(max))
Insert into #table values ('1'),('2'),('2'),('All'),('3'),('4')
select * from #table
--select * from #table order by id
select * from #table order by case when id = 'All' then 0 else id end
Another twist, suppose you have 2 varchar entry still this logic work as
Declare #table table (id varchar(max))
Insert into #table values ('1'),('2'),('2'),('All'),('3'),('4'),('Select')
select * from #table
select * from #table order by id
select * from #table order by case when id in ( 'All' , 'Select') then 0 else id end
You can use GROUP BY (instead of DISTINCT) with #jarlh 's suggestion for the ORDER BY clause in the comments above (tweaked ever so slightly).
SELECT
Strategy
FROM
#Strategy
GROUP BY
Strategy
ORDER BY
CASE WHEN Strategy = 'All' THEN 0 ELSE Strategy END
Or by continuing to use DISTINCT you can move the CASE statement to the SELECT clause to create a new column to use in the ORDER BY clause:
SELECT DISTINCT
Strategy
,CASE WHEN Strategy = 'All' THEN 0 ELSE Strategy END AS SortOrder
FROM
#Strategy
ORDER BY
SortOrder
Or if the order of the subsequent items doesn't matter just keep it simple as #ChrisChurch suggests.

Duplicate Counts - TSQL

I want to get All records that has duplicate values for SOME of the fields (i.e. Key columns).
My code:
CREATE TABLE #TEMP (ID int, Descp varchar(5), Extra varchar(6))
INSERT INTO #Temp
SELECT 1,'One','Extra1'
UNION ALL
SELECT 2,'Two','Extra2'
UNION ALL
SELECT 3,'Three','Extra3'
UNION ALL
SELECT 1,'One','Extra4'
SELECT ID, Descp, Extra FROM #TEMP
;WITH Temp_CTE AS
(SELECT *
, ROW_NUMBER() OVER (PARTITION BY ID, Descp ORDER BY (SELECT 0))
AS DuplicateRowNumber
FROM #TEMP
)
SELECT * FROM Temp_cte
DROP TABLE #TEMP
The last column tells me how many times each row has appeared based on ID and Descp values.
I want that row but I ALSO need another column* that indicates both rows for ID = 1 and Descp = 'One' has showed up more than once.
So an extra column* (i.e. MultipleOccurances (bool)) which has 1 for two rows with ID = 1 and Descp = 'One' and 0 for other rows as they are only showing up once.
How can I achieve that? (I want to avoid using Count(1)>1 or something if possible.
Edit:
Desired output:
ID Descp Extra DuplicateRowNumber IsMultiple
1 One Extra1 1 1
1 One Extra4 2 1
2 Two Extra2 1 0
3 Three Extra3 1 0
SQL Fiddle
You say "I want to avoid using Count" but it is probably the best way. It uses the partitioning you already have on the row_number
SELECT *,
ROW_NUMBER() OVER (PARTITION BY ID, Descp
ORDER BY (SELECT 0)) AS DuplicateRowNumber,
CASE
WHEN COUNT(*) OVER (PARTITION BY ID, Descp) > 1 THEN 1
ELSE 0
END AS IsMultiple
FROM #Temp
And the execution plan just shows a single sort
Well, I have this solution, but using a Count...
SELECT T1.*,
ROW_NUMBER() OVER (PARTITION BY T1.ID, T1.Descp ORDER BY (SELECT 0)) AS DuplicateRowNumber,
CASE WHEN T2.C = 1 THEN 0 ELSE 1 END MultipleOcurrences FROM #temp T1
INNER JOIN
(SELECT ID, Descp, COUNT(1) C FROM #TEMP GROUP BY ID, Descp) T2
ON T1.ID = T2.ID AND T1.Descp = T2.Descp

How to create a sum column without an internal subquery?

I'm using SQL Server 2008 R2
I have a complex query which I need to have a conditionally summed column for it.
Here is a simplified version of my query and results:
DECLARE #t TABLE (id int, condition int, value int);
INSERT INTO #t
VALUES (1,1,12), (2,0,88), (3,1,11)
SELECT
*,
(SELECT SUM(value) FROM #t WHERE condition = 1) as SumOfConditionalValues
FROM #t
Here are the results of this query"
id condition value SumOfConditionalValues
1 1 12 23
2 0 88 23
3 1 11 23
I can't afford the SumOfConditionalValues sub query.
Is there an elegant way to achieve the conditionally summed column without it?
Which aggregate commands are suitable here, if any, and how do I apply these?
Try this:
SELECT *, SUM(CASE WHEN condition = 1 THEN value END) OVER() SumOfConditionalValues
FROM #t
See here: http://sqlfiddle.com/#!3/1abea/1
Use a self join:
CREATE TABLE MyTable (id int, condition int, value int);
INSERT INTO MyTable
VALUES (1,1,12), (2,0,88), (3,1,11)
SELECT
MyTable.id,
MyTable.Condition,
MyTable.value,
SUM(JoinedMyTable.Value)
FROM
MyTable
LEFT JOIN MyTable JoinedMyTable ON MyTable.condition = JoinedMyTable.Condition
GROUP BY
MyTable.id,
MyTable.Condition,
MyTable.value
EDIT: Don't know if you want every row to show the sum of rows where condition = 1, but if you do just change the join clause to be:
LEFT JOIN MyTable JoinedMyTable ON JoinedMyTable.Condition = 1
I believe what you are looking for is the "CASE' statement...Very powerful, for example:
select id, sum(case when condition=1 then value else 0 end) group by id..etc
Declare #sum int
SELECT #sum=SUM(value) FROM #t WHERE condition = 1
select *,#sum from yourtable
You can bring the results aggregated by condition:
DECLARE #t TABLE (id int, condition int, value int);
INSERT INTO #t VALUES (1,1,12), (2,0,88), (3,1,11)
SELECT *,
sum(value) over (partition by condition) as SumOfConditionalValues
FROM #t
I think this is what you want:
SELECT id, condition, value,
SUM(CASE WHEN condition = 1 THEN value_at_1 END) OVER() SumOfConditionalValues
FROM (select *,
(case when condition = 1 then value end) as value_at_1
from #t
) t
You need a "conditional value", which you can create in a subquery.