SQL query ordered alphabetically - sql

I have a table as below,
ID Description
--------------------
1 Bacteria
2 Cell Lines
3 Compounds
4 Virus
5 Others
6 AntiBody
What I want is a single SQL query, ordered alphabetically but have 'Other' (ID 5) as the last record.
Is that even possible?
Any help would greatly appreciated.
Thanks.

SELECT ID, Description
FROM YourTable
ORDER BY CASE WHEN ID = 5 THEN 1 ELSE 0 END,
Description

SELECT ID, Description
FROM yourtable
ORDER BY CASE WHEN Description = 'Others' THEN 1 ELSE 0 END, Description

Related

SQL Server -- Join Issue

I have a table with following rows :
SectionId
SectionStatus
1
Assigned
1
Approved
2
Assigned
2
Assigned
3
Assigned
Now I want to fetch the SectionId where al SectionStatus belong to that SectionId are not Approved.
Result expected for above table : 1,2,3
Another Example :
SectionId
SectionStatus
1
Approved
1
Approved
2
Assigned
2
Assigned
3
Assigned
Result expected for above table : 2,3
This looks like aggregation with a conditional count in the HAVING clause.
SELECT t.SectionId
FROM yourtable t
GROUP BY t.SectionId
HAVING COUNT(CASE WHEN t.SectionStatus = 'Approved' THEN 1 END) = 0;
db<>fiddle
One way to get that is by cross-applying the record and check whether that is 'Approved' or not.
Try the following:
select distinct SectionId from yourtable tab
cross apply (select 'Approved' Stat)t
where t.Stat <> tab.SectionStatus
Please see the db<>fiddle here.

SQL Conditional Aggregation not returning all expected rows

So I've been trying to get a conditional aggregation running on one of my tables in SQL Server Management Studio and I've run across a problem: only one row is being returned when there should be 2.
SELECT ListID,
MAX(CASE WHEN QuestionName = 'Probability Value' THEN Answer END) AS 'prob',
MAX(CASE WHEN QuestionName = 'Impact Value' THEN Answer END) As 'impa',
MAX(CASE WHEN QuestionName = 'What is the Risk Response Strategy' THEN Answer END) AS 'strat',
MAX(CASE WHEN QuestionName = 'Response Comment' THEN Answer END) AS 'rrap'
FROM table1
GROUP BY ListID
By the information stored on the table is should return two rows, something like:
ListID | Prob | Impa | Strat | rrap |
1 2 3 Admin text1
1 5 5 Elim text2
but only the first row appears. I don't have any good leads at the moment, but I wonder if you good people might have spotted something obviously wrong with the initial query.
Your only group by is ListID and your 2 rows both have 1 on ListID, that's why they group up
Why do you think it should return more than 1 row? You are grouping by ListID and getting the MAX answer for all these questions.
If you want more rows returned you will have to group by other columns/expressions as well. You can't expect ListID 1 to appear more than once if you grouped by ListID only.

How to use partition in sql

I tried to find out and came to the conclusion that partition should used for this task. But, I've never used this before.
I have a table like:
id status
1 3
2 1
1 4
3 2
3 3
1 5
I want to get list of all id's that don't have status as 5. Please help!!
SELECT ID
FROM table_name
GROUP BY ID
HAVING COUNT( CASE status WHEN 5 THEN 1 END ) = 0
As simple as possible I think this would work for you. Your example could be more specific so I hope this is what you are trying to do.
SELECT DISTINCT id
FROM table_name
WHERE id NOT IN (SELECT id FROM table_name WHERE status = 5);
You wouldn't need partition to perform this task. All you have to do is
select id from
where status not in ('5')

Selecting count by row combinations

I'm strugling with what on the first sight appeared to be simple SQL query :)
So I have following table which has three columns: PlayerId, Gender, Result (all of type integer).
What I'm trying to do, is to select distinct players of gender 2 (male) with number of each results.
There are about 50 possible results, so new table should have 51 columns:
|PlayerId | 1 | 2 | 3 | ... | 50 |
So I would like to see how many times each individual male (gender 2) player got specific result.
*** In case question is still not entirely clear to you: After each game I insert a row with a player ID, gender and result (from 1 - 50) player achieved in that game. Now I'd like to see how many times each player achieved specfic results.
If there are 50 results and you want them in columns, then you are talking about a pivot. I tend to do these with conditional aggregation:
select player,
sum(case when result = 0 then 1 else 0 end) as result_00,
sum(case when result = 1 then 1 else 0 end) as result_01,
. . .
sum(case when result = 50 then 1 else 0 end) as result_50
from t
group by player;
You can choose a particular gender if you like, with where gender = 2. But why not calculate all at the same time?
try
select player, result, count(*)
from your_table
where Gender = 2
group by player, result;
select PleyerId from tablename where result = 'specific result you want' and gender = 2 group by PleyerId
The easiest way is to use pivoting:
;with cte as(Select * from t
Where gender = 2)
Select * from cte
Pivot(count(gender) for result in([1],[2],[3],....,[50]))p
Fiddle http://sqlfiddle.com/#!3/8dad5/3
One note: keeping gender in scores table is a bad idea. Better make a separate table for players and keep gender there.

Exclude value of a record in a group if another is present v2

In the example table below, I'm trying to figure out a way to sum amount over marks in two situations: the first, when mark 'C' exists within a single id, and the second, when mark 'C' doesn't exist within an id (see id 1 or 2). In the first situation, I want to exclude the amount against mark 'A' within that id (see id 3 in the desired conversion table below). In the second situation, I want to perform no exclusion and take a simple sum of the amounts against the marks.
In other words, for id's containing both mark 'A' and 'C', I want to make the amount against 'A' as zero. For id's that do not contain mark 'C' but contain mark 'A', keep the original amount against mark 'A'.
My desired output is at the bottom. I've considered trying to partition over id or use the EXISTS command, but I'm having trouble conceptualizing the solution. If any of you could take a look and point me in the right direction, it would be greatly appreciated :)
example table:
id mark amount
------------------
1 A 1
2 A 3
2 B 2
3 A 1
3 C 3
desired conversion:
id mark amount
------------------
1 A 1
2 A 3
2 B 2
3 A 0
3 C 3
desired output:
mark sum(amount)
--------------------
A 4
B 2
C 3
You could slightly modify my previous answer and end up with this:
SELECT
mark,
sum(amount) AS sum_amount
FROM atable t
WHERE mark <> 'A'
OR NOT EXISTS (
SELECT *
FROM atable
WHERE id = t.id
AND mark = 'C'
)
GROUP BY
mark
;
There's a live demo at SQL Fiddle.
Try:
select
mark,
sum(amount)
from ( select
id,
mark,
case
when (mark = 'A' and id in (select id from table where mark = 'C')) then 0
else amount
end as amount
from table ) t1
group by mark