Subtract values from one column based on values in another (TSQL) - sql

I have table where I need to subtract values in one column based on conditions applied to the other. For example, I want to subtract values with code fst and trd, meaning (12 - 23).
I don't want to declare separate variables. Is it possible to make this with a query?

One method is conditional aggregation:
select sum(case when code = 'fst' then value else - value end)
from t
where code in ('fst', 'trd');
Assuming you have only one row for each code, you can also use a join:
select tf.value - tt.value
from t tf join
t tt
on tf.code = 'fst' and tt.code = 'trd'

Related

SQLite split column on another column's value

I have a database in which multiple variables appear as consecutive rows (shown below, variables differentiated by their tags). As a result, their values appear as consecutive rows in the 'value' column.
Existing table:
For data analysis, I need to split each variable's value into separate columns, as illustrated below.
The SQLite query is listed below. I have tried using GROUP BY tag and averaging the values, but the result becomes too granular to be useful.
Advice would be much appreciated!
SELECT
tag
,time
,value
FROM
[archive]..[interp]
WHERE
tag
IN
( 'flow1.Val'
, 'flow2.Val'
, 'density1.Val'
, 'density2.Val'
)
AND
time
BETWEEN
't-1d' and 't'
AND
timestep = '1h'
You can use conditional aggregation:
select time,
max(case when tag = 'flow1.Val' then value end) as flow1_val,
max(case when tag = 'flow2.Val' then value end) as flow2_val,
max(case when tag = 'density1.Val' then value end) as density1_val,
max(case when tag = 'density2.Val' then value end) as density2_val
from [archive]..[interp]
group by time
Depending on your actual requirement, you might want to use another aggregate function than max(), it you have more than one row for a given time/tag tuple.

Convert null values to zero in crosstab query

The code below is a subset of a larger code that results in a cross tab query. The issue is that the total column to the right which sums all the number columns in the cross tab query does not calculate accurately as it results a 0 for any rows that have null value in one of the twelve columns it is attempting to sum.
I believe that the i need to add a condition to the following line in the code to result in a zero if the value is null. I just need someone to take a second look at it. If there is a better alternate solution, I am happy to entertain that also.
SUM(entry) for MX in (M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12)
SELECT
tblCenters.prop
,tblAccounts.Category_EXCO
,tblCenters.CenterNum
,tblAccounts.AccountNum
,tblAccounts.Account_Description
,tblAccounts.Is_Revenue
,tblAccounts.Is_Above_EBITDA
,tblCenters.Division_Description
,tblCenters.[Is_F&B1]
,tblCenters.Group_Description
,Entry
,MX
FROM GA_Financial.dbo.tblSAP
left join tblMX on tblSAP.MDY = tblMX.MDY
left join tblAccounts on tblSAP.AccountNum = tblAccounts.AccountNum
left join tblCenters on tblSAP.CenterNum = tblCenters.CenterNum and tblSAP.Prop_SAP = tblCenters.PROP_SAP
WHERE tblAccounts.Is_Above_EBITDA = 1
AND tblSAP.Type = 'A'
)
AS Tab1
--The code below breaks down column "Entry" into twelve individual monthly columns and fills columns M1 through M12
PIVOT
(
SUM(entry) for MX in (M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12)
) as TAb2
where Prop = 'RWNY'
I think that you can use the COALESCE or IFNULL functions to replace the null value with a 0 for the sum calculation. Check out this response: COALESCE, IFNULL, or NZ() function that can be used in SQL Server and MS Access
To avoid a null result use ISNULL(Entry, 0) instead of Entry in your original query. This will substitute any returned null's with 0's.

Hive - How to calculate if all records inside a groupby have the same value in a specific column?

I am grouping by records base on one column. What I want to know if all of these records has got the same value in another column.
So far I achieve this with the following logic, which I believe is too complex:
select number,
if(flagSum = 0 OR flagSum = groupedrecords, "AllSame", "SomeDifferent") as AllIndicatorEqual
from
(select number,
sum(if(flag = 'Y', 1, 0)) as flagSum,
count(*) as groupedrecords
from table
where number = '1234'
group by number
)tab
So basically I group by number, and check if all records grouped has got the same flag value.
Is there a more efficient way to calculate this?
You could probably skip a subquery by using a distinct count :
select
number,
if(count(distinct flag) = 1, "AllSame", "SomeDifferent") as AllIndicatorEqual
from table
group by number;
http://sqlfiddle.com/#!9/20e024/6

Query to return the amount of time each field equals a true value

I'm collecting data and storing in SQL Server. The table consist of the data shown in the Example Table below. I need to show the amount of time that each field [Fault0-Fault10] is in a fault state. The fault state is represented as a 1 for the fields value.
I have used the following query and got the desired results. However this is for only one field. I need to have the total time for each field in one query. I'm having issues pulling all of the fields into one query.
SELECT
Distinct [Fault0]
,datediff(mi, min(DateAndTime), max(DateAndTime)) TotalTimeInMins
FROM [dbo].[Fault]
Where Fault0 =1
group by [Fault0]
Results
Assuming you want the max() - min(), then you simply need to unpivot the data. Your query can look like:
SELECT v.faultname,
datediff(minute, min(t.DateAndTime), max(t.DateAndTime)) as TotalTimeInMins
FROM [dbo].[Fault] f CROSS APPLY
(VALUES ('fault0', fault0), ('fault1', fault1), . . ., ('fault10', fault10)
) v(faultname, value)
WHERE v.value = 1
GROUP BY v.faultname;

Complex Calculation - SQL Server

I'm currently working on calculating a larger set of data with a number of joins and the end result is a calculation across two tables. My current script looks like the following:
USE db1
Go
SELECT
customer, tb1.custid
FROM
[dbo].[tb1]
LEFT OUTER JOIN
[dbo].[tb2] ON tb1.custid = tb2.custid
LEFT OUTER JOIN
[dbo].[tb3] ON tb2.custnumber = tb3.custnumber
LEFT OUTER JOIN
[dbo].[tb4] ON tb2.custid = tb4.custid
WHERE
tb1.custclass = 'non-person'
AND tb4.zip IN ('11111', '11112')
GO
As you can see, it's not the cleanest, but it's working for gathering initial information. The reasoning for the number of joins is due to an incredibly odd table structure I did not create and the fact that the numerical data I need is only stored in tb3.
What I'm now trying to do is calculate the sum of 3 fields from tb3 that are all set as numeric fields and do an AND/OR comparison against a 4th field (also numeric). I know I can SUM them together, but I'm hoping for some input on three things:
Where to place that SUM calculation in the query?
Where to place and how to do the comparison of the SUM total against the 4th field?
Is it possible to return the higher of the two values to a TOTAL column in the initial SELECT?
Thank you in advance.
Where to place that SUM calculation in the query?
If you want it output, you probably want to just add it to the SELECT
SELECT
customer, tb1.custid
(tb3.col1 + tb3.col2 + tb3.col3) as Sum
FROM
...
Where to place and how to do the comparison of the SUM total against the 4th field?
You probably want to do this with a CASE statement, and this also answers your last question
Is it possible to return the higher of the two values to a TOTAL column in the initial SELECT?
SELECT
customer, tb1.custid
CASE WHEN (tb3.col1 + tb3.col2 + tb3.col3) > tb3.col4
THEN (tb3.col1 + tb3.col2 + tb3.col3)
ELSE tb3.col4
END as Total
FROM
...
You should be able to calculate the sum as a nested query:
SELECT (field1 + field2 + field3) AS fields_sum FROM tb3 (...)
Then in your main query you could do something like:
SELECT customer, tb1.custid, (CASE WHEN fields_sum > fourth_field THEN fields_sum ELSE fourth_field END) AS TOTAL (...)