I have a table witch hold random numbers - for example (1, 2, 4, 6, 8, 10).
Is it possible to select the sum of numbers that are below 5 and the sum of numbers that are above 5 within one query?
Something like:
SELECT sum(numbers_below_five), sum(numbers_above_five) from numbers
If it is possible then is there point in doing so or would two queries faster?
You can use a case statement for this:
SELECT
SUM (CASE WHEN n > 5 THEN n ELSE 0 END) as SumGreaterThanFive,
SUM (CASE WHEN n <= 5 THEN n ELSE 0 END) as SumLessThanFive
FROM myTable
Assuming that accessing your RDBMS requires a network roundtrip, a single query should be faster than two queries.
SELECT sum(case when num_column < 5 then num_column end) as numbers_below_five,
sum(case when num_column > 5 then num_column end) as numbers_above_five
from numbers
Related
A table (ex: A) has three columns id, name, amount. Amount has some +ve,-ve and zero values. How to write a query to get the amount in such a way that it gives as a result first +ve then -ve then zeros? PFA for the sample table.
Thanks in advance
If you want 3 groups one after the other:
SELECT *
FROM tablename
ORDER BY
(CASE
WHEN amount > 0 then 1
WHEN amount < 0 then 2
ELSE 3
END),
Id;
Are you just looking for order by with a case expression?
select a.*
from a
order by (case when a.amount > 0 then 1
when a.amount < 0 then 2
else 3
end),
a.amount desc;
I'd like to have the average of a column when its bigger than zero.
Select Avg(Case when Column > 0 then Column else 0 end) as Avg
but I'm afraid the else clause is not correct. I want to ignore the zero values in the average.
Remove else part from case statement so the values less than 1 will be NULL.
Null values will be eliminated by the Avg aggregate. So you will get the average of values which are greater then 0. Try this.
Select Avg(Case when [Column]>0 then [Column] end) as [Avg]
DEMO
Without else part in case statement (Expected Average)
SELECT Avg(CASE WHEN a > 0 THEN a END) [Avg]
FROM (SELECT 2 a UNION ALL SELECT 2 UNION ALL SELECT -1) bb
Result : 2
With else part in case statement.
SELECT Avg(CASE WHEN a > 0 THEN a ELSE 0 END) [Avg]
FROM (SELECT 2 a UNION ALL SELECT 2 UNION ALL SELECT -1) bb
Result : 1
I have a table named A that contains a column named x. What I'm trying to do is to count the number of items that belong to a certain subset of A (more precisely, the ones that satisfy the x > 4 condition) via a single SELECT query, for example:
SELECT COUNT(*)
FROM A
WHERE x > 4;
From thereon, I'd like to calculate the ratio between the size of this particular subset of A and A as a whole, i.e. perform the following division:
size_subset / size_A
My question is - how would I combine all of these pieces into a single SQL SELECT query?
My server is down, not able to get sure of the answer below:
SELECT count(case when x > 4 then x else null end) / COUNT(*) FROM A;
Is a slight better because its just a count, not a sum (nulls ill not be accounted)
but i prefer to do:
select (SELECT count(*) FROM A where x > 4)/(SELECT count(*) FROM A);
As I guess it can do faster
You want conditional aggregation:
SELECT sum(case when x > 4 then 1 else 0 end) / COUNT(*)
FROM A;
There's probably a less clunky way of doing this, but:
SELECT SUM(CASE WHEN x > 4 THEN 1 ELSE 0 END) / COUNT(*) FROM A
This question already has an answer here:
OrderBy in SQL Server to put positive values before negative values
(1 answer)
Closed 9 years ago.
How do I need to show the positive numbers first and then negative numbers while sorting the numbers in SQL Server 2008.
Ex:
Lets say I have numbers -4,-3,null,2,3
Then expected result : 2,3,-4,-3,null
Based on your small example, it seems that you want the positive numbers in increasing order and then the negative numbers in increasing order.
That makes the problem slightly more interesting. Try this order by clause:
order by (case when col > 0 then 2 when col < 0 then 1 else 0 end) desc,
col asc
Here is an example:
with t as (select 2 as col union all select 3 union all select -4 union all select -3 union all select null)
select *
from t
order by (case when col > 0 then 2 when col < 0 then 1 else 0 end) desc,
col asc;
I have a table and I need calculate two aggregate functions with different conditions in one statement. How can I do this?
Pseudocode below:
SELECT count(CoumntA) *< 0*, count(CoumntA) * > 0*
FROM dbo.TableA
This is the same idea as tombom's answer, but with SQL Server syntax:
SELECT
SUM(CASE WHEN CoumntA < 0 THEN 1 ELSE 0 END) AS LessThanZero,
SUM(CASE WHEN CoumntA > 0 THEN 1 ELSE 0 END) AS GreaterThanZero
FROM TableA
As #tombom demonstrated, this can be done as a single query. But it doesn't mean that it should be.
SELECT
SUM(CASE WHEN CoumntA < 0 THEN 1 ELSE 0 END) AS less_than_zero,
SUM(CASE WHEN CoumntA > 0 THEN 1 ELSE 0 END) AS greater_than_zero
FROM
TableA
The time when this is not so good is...
- There is an index on CoumntA
- Most values (50% or more feels about right) are exactly zero
In that case, two queries will be faster. This is because each query can use the index to quickly home in on the section to be counted. In the end only counting the relevant records.
The example I gave, however, scans the whole table every time. Only once, but always the whole table. This is worth it when you're counting most of the records. In your case it looks liek you're counting most or all of them, and so this is probably a good way of doing it.
It is possible to do this in one select statement.
The way I've done it before is like this:
SELECT SUM(CASE WHEN ColumnA < 0 THEN 1 END) AS LessThanZero,
SUM(CASE WHEN ColumnA > 0 THEN 1 END) AS GreaterThanZero
FROM dbo.TableA
This is the correct MS SQL syntax and I believe this is a very efficient way of doing it.
Don't forget you are not covering the case when ColumnA = 0!
select '< 0' as filter, COUNT(0) as cnt from TableA where [condition 1]
union
select '> 0' as filter, COUNT(0) as cnt from TableA where [condition 2]
Be sure that condition 1 and condition 2 create a partition on the original set of records, otherwise same records could be counted in both groups.
For SQL Server, one way would be;
SELECT COUNT(CASE WHEN CoumntA<0 THEN 1 ELSE NULL END),
COUNT(CASE WHEN CoumntA>0 THEN 1 ELSE NULL END)
FROM dbo.TableA
Demo here.
SELECT
SUM(IF(CoumntA < 0, 1, 0)) AS lowerThanZero,
SUM(IF(CoumntA > 0, 1, 0)) AS greaterThanZero
FROM
TableA
Is it clear what's happening? Ask, if you have any more questions.
A shorter form would be
SELECT
SUM(CoumntA < 0) AS lowerThanZero,
SUM(CoumntA > 0) AS greaterThanZero
FROM
TableA
This is possible, since in MySQL a true condition is equal 1, a false condition is equal 0
EDIT: okay, okay, sorry, don't know why I thought it's about MySQL here.
See the other answers about correct syntax.