Multiply within same column - sql

I have a table that looks like the following:
label
value
student1
90
student2
88
student3
59
student4
77
I am trying to multiply two values if they meet the condition.
For example, I want to multiply values for student 1 and 3 together. Then I want to multiply the values for student 2 and 4.
For the first criteria, I tried the following code:
select
case
when
max(label) = "student1" or max(label) = "student3" then exp(SUM(log(value))) else 0 end as nominator
from four_students_table
Unfortunately, it gives me the value of 0. I have also tried to just add them together, but got 0 again. I am not sure what I am doing wrong here.
Expected output:
numerator
denominator
5,310
6,776

I case statement as shown in the example below would assist in filtering what you would like to aggregrate.
The following fiddle provides your desired results:
CREATE TABLE four_students_table (
label VARCHAR(8),
value INTEGER
);
INSERT INTO four_students_table
(label, value)
VALUES
('student1', '90'),
('student2', '88'),
('student3', '59'),
('student4', '77');
Query #1
SELECT
SUM(CASE WHEN label='student1' THEN value ELSE 0 END)*
SUM(CASE WHEN label='student3' THEN value ELSE 0 END) as nominator,
SUM(CASE WHEN label='student2' THEN value ELSE 0 END)*
SUM(CASE WHEN label='student4' THEN value ELSE 0 END) as denominator
FROM
four_students_table;
nominator
denominator
5310
6776
View on DB Fiddle

Consider below (I feel this is more inline with your intends/sample in your question)
select distinct
round(exp(sum(if(label in ('student1', 'student3'), ln(value), 0)) over())) as nominator,
round(exp(sum(if(label in ('student2', 'student4'), ln(value), 0)) over())) as denominator
from `project.dataset.four_students_table`
if applied to sample data in your question - output is

Related

Two different condition for two different colums using case statement in SQL

Given a table of random numbers as follows:
** Person table schema **
Name
Marks1
Marks2
I want to return a table with similar structure and headings, where if the sum of a column is odd, the column shows the maximum value for that column, and when the sum is even, it shows the minimum value by using a case statement.
** output table schema **
Marks1
Marks2
I've tried the following code.
select Marks1,Marks2 ,
(case
when mod(sum(Marks1),2)=0 then
min(Marks1)
else max(Marks1)
end) as Marks1 ,
(case
when mod(sum(Marks2),2)=0 then
min(Marks2)
else max(Marks2)
end) as Marks2
from numbers
group by Marks1;
Sample output -
TABLE
Ash 56 45
David 45 35
Output -
56 35
As 56+45 = 101 odd number so output 56(max number). Whereas in marks2 column, 45+35 =80, even number so output 35(min number).
Can anyone tell me what's wrong with it? Thanks in advance.
Use a CTE to get your min(), max(), and sum() values. Then use case to determine what values to display.
Since your problem statement and sample results do not match, I followed your sample results to return max() on an odd sum(). You can switch this by changing the two case statements from 1 to 0.
Working fiddle
with totals as (
select sum(marks1) as marks1sum,
min(marks1) as marks1min,
max(marks1) as marks1max,
sum(marks2) as marks2sum,
min(marks2) as marks2min,
max(marks2) as marks2max
from numbers
)
select case mod(marks1sum, 2)
when 1 then marks1max
else marks1min
end as marks1,
case mod(marks2sum, 2)
when 1 then marks2max
else marks2min
end as marks2
from totals;
You are reusing marks1 and marks2 when aliasing your third and fourth column which is colliding. Try using different name.

How can I find values with more than 2 decimal places?

I am validating data and trying to find if there are any values in a single column (allowed_amount) with more than 2 decimal places (24.1145678, 234.444, -1234.09012).
with t1 as (
select (allowed_amount - round(allowed_amount,2)) as ck
from export_core_report_client_output
where runid = '0c7c2d34-6cc3-43b0-ae4b-4bd8f4bddfb0'
)
select min(ck) as min, max(ck) as max from t1
One option would be to use this formula:
SELECT
num,
CASE WHEN 100*num - CAST(100*num AS int) > 0 THEN 'yes' ELSE 'no' END AS field
FROM yourTable;
Demo
For example, for the value 24.1234, the above formula computes:
2412.34 - 2412 = 0.34 > 0
But for 24.12, we get:
2412 - 2412 = 0
You can use Charindex to do that, supposing the allowed_amount column is varchar or nvarchar
select len(substring(allowed_amount,charindex('.',allowed_amount)+1,len(allowed_amount))) from export_core_report_client_output
This will give you a count of decimal values after and then you can use the same statement in where clause to scrutinize like:
select len(substring(allowed_amount,charindex('.',allowed_amount)+1,len(allowed_amount))) from export_core_report_client_output
where len(substring(allowed_amount,charindex('.',allowed_amount)+1,len(allowed_amount)))> 2
any questions fire up in the comments

Count number of + and - values based on another column

I am trying to get a simple count of all the negative and positive values of a specific column on my database. I want to be able to count these values based on another column. What would be the best way to go about handling this problem.
enter image description here
Something like this:
SELECT
SUM(CASE WHEN column > 0 THEN 1 ELSE 0 END) as count_positive,
SUM(CASE WHEN column < 0 THEN 1 ELSE 0 END) as count_negative
FROM
table
You must put the column name, table name, and decide whether 0 is positive, negative or excluded (my choice)

Issue with case when SQL

I have a table named 'candidate' which contains among others columns ,score_math' and 'score_language' reflecting candidate's score in respective tests. I need to
Show the number of students who scored at least 60 in both math and language (versatile_candidates) and the number of students who scored below 40 in both of
these tests (poor_candidates). Don't include students with NULL preferred_contact. My query is:
select
count(case when score_math>=60 and score_language>=60 then 1 else 0
end) as versatile_candidates,
count(case when score_math<40 and score_language<40 then 1 else 0 end) as
poor_candidates
from candidate
where preferred_contact is not null
But this produces always total number of candidates wit not-null preferred contact type. Can't really figure out what I did wrong and more importantly why this doesn't work. [DBMS is Postgres if this matters ]Please help
You're close - the reason you're getting the total number of all candidates is because COUNT() will count a 0 the same as a 1 (and any other non-NULL value, for that matter). And since the values could only ever be 0 or 1, your COUNT() will return the total number of all candidates.
Since you're already defaulting the cases that don't match to 0, all you need to do is change the COUNT() to a SUM():
Select Sum(Case When score_math >= 60
And score_language >= 60 Then 1
Else 0
End) As versatile_candidates
, Sum(Case When score_math < 40
And score_language < 40 Then 1
Else 0
End) As poor_candidates
From candidate
Where preferred_contact Is Not Null
COUNT() does not take into consideration NULL values. All other values which are not NULL will be counted.
You might want to replace it with SUM()

Counting non-zero values in sql

I am trying to count total number of times that each individual column is greater than zero, grouped by the driver name. Right now I have;
SELECT drivername
, COUNT(over_rpm) AS RPMViolations
, COUNT(over_spd) AS SpdViolations
, COUNT(brake_events) AS BrakeEvents
FROM performxbydriverdata
WHERE over_rpm > 0
OR over_spd > 0
OR brake_events > 0
GROUP BY drivername
This gives me all of the non-zero values but I get a display as:
Bob Smith 62 62 62
Nathan Jones 65 65 65
etc.
I'm trying to get a count of non-zeros in each individual values.. each violation should be grouped separately.
Use NULLIF to change zero to NULL, count ignores NULL
SELECT drivername,
COUNT(NULLIF(over_rpm,0)) AS RPMViolations,
COUNT(NULLIF(over_spd,0)) AS SpdViolations,
COUNT(NULLIF(brake_events,0)) AS BrakeEvents
FROM performxbydriverdata
GROUP BY drivername;
You can probably remove the WHERE clause too with this group to improve performance
OR conditions often run badly because of matching a good index
Using HAVING (as per other answers) will remove any rows where all 3 aggregates are zero which may or may not be useful for you. You can add this if you want. Saying that, the WHERE implies that at least one row has non-zero values so you don't need both WHERE and HAVING clauses
Putting filter predicate[s] inside of a Sum() function with a case statement is a useful trick anytime you need to count items based on some predicate condition.
Select DriverName,
Sum(case When over_rpm > 0 Then 1 Else 0 End) OverRpm,
Sum(case When over_spd > 0 Then 1 Else 0 End) OverSpeed,
Sum(case When brake_events > 0 Then 1 Else 0 End) BrakeEvents,
etc.
FROM performxbydriverdata
Group By DriverName