Add new column in SQL based on 2 conditions - sql

I would like to create a new column in SQL using two conditions. I want to create a column that says 1 if the item count is greater than 1 and if item/sum is greater than 5, otherwise return 0. This is not my original data, is there anyway I could add this new column with these specified rows using a select statement.

First I want to say that using SQL key words or SQL function names as table name or column name should be avoided, so if possible, I recommend to rename the columns "number" and "sum".
The second point is it's unclear what should happen in case the sum column is 0. Since a division by zero is not possible, you will need to add a condition for that.
Anyway, the way to achieve such things is using CASE WHEN. So let's add the new column:
ALTER TABLE yourtable ADD column column_name INT;
Now, you need to execute an update command for that column providing the logic you want to apply. As an example, you can do this:
UPDATE yourtable SET column_name =
CASE WHEN item <= 1 THEN 0
WHEN sum = 0 THEN 1
WHEN item / sum > 0.5 THEN 1
ELSE 0 END;
This will set the new column to 1 only in case item is > 1 and sum is 0 or sum item / sum is > 0.5 (greater 50%). In all other cases it will be set to 0. Again, the bad column naming can be seen since "WHEN sum..." looks like you really build a sum and not just use a column.
If you want as example to set the new column to 0 instead of 1 when the sum is 0, just change it and try out.
In case you want to automatically apply this logic fur future inserts or updates, you can add a trigger on your new column. Something like this:
CREATE TRIGGER set_column_name
BEFORE INSERT ON yourtable
FOR EACH ROW
SET new.column_name = CASE WHEN new.item <= 1 THEN 0
WHEN new.sum = 0 THEN 1
WHEN new.item / new.sum > 0.5 THEN 1
ELSE 0 END;
But take care, the syntax of triggers depend on the DB you are using (this example will work in MYSQL). Since you did not tell us which DB you use, you maybe need to modify it. Furthermore, depending on your DB type and your requirements, you need zero, one or two triggers (for updates and for inserts).

Related

Sql column value as formula in select

Can I select a column based on another column's value being listed as a formula? So I have a table, something like:
column_name formula val
one NULL 1
two NULL 2
three one + two NULL
And I want to do
SELECT
column_name,
CASE WHEN formula IS NULL
val
ELSE
(Here's where I'm confused - How do I evaluate the formula?)
END as result
FROM
table
And end up with a result set like
column_name result
one 1
two 2
three 3
You keep saying column, and column name, but you're actually talking about rows, not columns.
The problem is that you (potentially) want different formulas for each row. For example, row 4 might be (two - one) = 1 or even (three + one) = 4, where you'd have to calculate row three before you could do row 4. This means that a simple select query that parses the formulas is going to be very hard to do, and it would have to be able to handle each type of formula, and even then if the formulas reference other formulas that only makes it harder.
If you have to be able to handle functions like (two + one) * five = 15 and two + one * five = 7, then you'd be basically re-implementing a full blown eval function. You might be better to return the SQL table to another language that has eval functions built in, or you could use something like SQL Eval.net if it has to be in SQL.
Either way, though, you've still got to change "two + one" to "2 + 1" before you can do the eval with it. Because these values are in other rows, you can't see those values in the row you're looking at. To get the value for "one" you have to do something like
Select val from table where column_name = 'one'
And even then if the val is null, that means it hasn't been calculated yet, and you have to come back and try again later.
If I had to do something like this, I would create a temporary table, and load the basic table into it. Then, I'd iterate over the rows with null values, trying to replace column names with the literal values. I'd run the eval over any formulas that had no symbols anymore, setting the val for those rows. If there were still rows with no val (ie they were waiting for another row to be done first), I'd go back and iterate again. At the end, you should have a val for every row, at which point it is a simple query to get your results.
Possible solution would be like this kind....but since you mentioned very few things so this works on your above condition, not sure for anything else.
GO
SELECT
t1.column_name,
CASE WHEN t1.formula IS NULL
t1.val
ELSE
(select sum(t2.val) from table as t2 where t2.formula is not null)
END as result
FROM
table as t1
GO
If this is not working feel free to discuss it further.

Qlikview - calculate and use calculated variable in script

As a new Qlikview user, I'm looking for the best way to create calculated variables, and variables based on calculated variables, in my data and use them in displays. My data is connected via ODBC.
For example, let's say I want a variable Rating based on the "Risk" variable in my dataset. The raw data contains a Risk variable that is "L" or "H". I would like to create an indicator, like Risk_H, that is 0 or 1 (if Risk='H'). Then I would like to create the Rating like "Rating = 1 + Risk_H*2". Can I do all of this in a script and have the variable Rating in my dataset?
When I try the above, I can create the Risk_H variable, but then I am not sure how to reference it in the script to calculate the Rating variable. I have read other posts that address using the load statement (Qlikview Calculated Fields with Load Script) but have been unsuccessful using calculated variables to create new variables.
Example code (which works):
SQL SELECT *,
case when (Risk = 'H') then 1
else 0
end as Risk_H
FROM [Data];
How can I create Risk_H in order to use it in the same script, like the below? In other settings, I would use something like "calculated Risk_H" to refer to it.
SQL SELECT *,
case when (Risk = 'H') then 1
else 0
end as Risk_H,
(10 + Risk_H*2) as Rating // Qlikview says it can't find Risk_H
FROM [Data];
I've tried creating Risk_H in a load script, but Qlikview doesn't recognize Risk_H in a later SQL statement. I've also tried creating a table with Risk_H , and pulling the data from that table. And in reality I'm trying to create 10+ indicators, not just one, so nested case statements aren't the answer.
EDIT: I'm told that resident tables may be the answer to performing calculations. If you can provide syntax for this using tables connected via ODBC that may answer the question.
It appears that your second Select statement is not valid SQL so as a result QlikView will complain that it cannot find Risk_H. You could try a more complicated SQL query with a sub-query to resolve this, or you could use a resident load in QlikView as follows:
Source_Data:
SQL SELECT *,
case when (Risk = 'H') then 1
else 0
end as Risk_H
FROM [Data];
Calculated_Data:
NOCONCATENATE
LOAD
*,
(10 + Risk_H*2) as Rating
RESIDENT Source_Data;
DROP TABLE Source_Data;
You also mentioned that you have around 10 indicators that you wish to use, so I agree, a case statement would probably not be a good idea. You can move this part into QlikView as well if you like using a MAPPING load and the ApplyMap function as follows:
Indicator_Map:
MAPPING
LOAD
*
INLINE [
Risk, Value
H, 1
I, 2
J, 3
];
Source_Data:
SQL SELECT *,
case when (Risk = 'H') then 1
else 0
end as Risk_H
FROM [Data];
Calculated_Data:
NOCONCATENATE
LOAD
*,
(10 + (ApplyMap('Indicator_Map',Risk, 0) * 2)) as Rating
RESIDENT Source_Data;
DROP TABLE Source_Data;
I added a couple of extra entries for your Risk "indicators" to give you an idea. Of course, the table doesn't need to be inline, it could come from another SQL statement, other file etc.
In the above example, what happens is that the Risk field's value is supplied as a parameter to the mapping table Indicator_Map which then returns the associated value. If no risk value is found, it returns 0 (the third parameter).

How to use multiple conditions (With AND) in IIF expressions in ssrs

I want to hide rows in SSRS report having Zero Quantity.
There are following multiple Quantity Columns like Opening Stock, Gross Dispatched,Transfer Out, Qty Sold, Stock Adjustment and Closing Stock etc.
I am doing this task by using following expression:
=IIF(Fields!OpeningStock.Value=0 AND Fields!GrossDispatched.Value=0 AND
Fields!TransferOutToMW.Value=0 AND Fields!TransferOutToDW.Value=0 AND
Fields!TransferOutToOW.Value=0 AND Fields!NetDispatched.Value=0 AND Fields!QtySold.Value=0
AND Fields!StockAdjustment.Value=0 AND Fields!ClosingStock.Value=0,True,False)
But by using this expression in row visibility, report hides all the rows except Totals Row. Even though report should show rows having Quantities of above mentioned columns.
Total values are shown correct.
Note: I set this row visibility expression on Detail Row.
Without using expression result is as following.
For the first 2 rows all the quantities are 0 (ZERO), i want to hide these 2 rows.
How can I fix this problem, or which expression must I use to get required results?
Could you try this out?
=IIF((Fields!OpeningStock.Value=0) AND (Fields!GrossDispatched.Value=0) AND
(Fields!TransferOutToMW.Value=0) AND (Fields!TransferOutToDW.Value=0) AND
(Fields!TransferOutToOW.Value=0) AND (Fields!NetDispatched.Value=0) AND (Fields!QtySold.Value=0)
AND (Fields!StockAdjustment.Value=0) AND (Fields!ClosingStock.Value=0),True,False)
Note: Setting Hidden to False will make the row visible
You don't need an IIF() at all here. The comparisons return true or false anyway.
Also, since this row visibility is on a group row, make sure you use the same aggregate function on the fields as you use in the fields in the row. So if your group row shows sums, then you'd put this in the Hidden property.
=Sum(Fields!OpeningStock.Value) = 0 And
Sum(Fields!GrossDispatched.Value) = 0 And
Sum(Fields!TransferOutToMW.Value) = 0 And
Sum(Fields!TransferOutToDW.Value) = 0 And
Sum(Fields!TransferOutToOW.Value) = 0 And
Sum(Fields!NetDispatched.Value) = 0 And
Sum(Fields!QtySold.Value) = 0 And
Sum(Fields!StockAdjustment.Value) = 0 And
Sum(Fields!ClosingStock.Value) = 0
But with the above version, if one record has value 1 and one has value -1 and all others are zero then sum is also zero and the row could be hidden. If that's not what you want you could write a more complex expression:
=Sum(
IIF(
Fields!OpeningStock.Value=0 AND
Fields!GrossDispatched.Value=0 AND
Fields!TransferOutToMW.Value=0 AND
Fields!TransferOutToDW.Value=0 AND
Fields!TransferOutToOW.Value=0 AND
Fields!NetDispatched.Value=0 AND
Fields!QtySold.Value=0 AND
Fields!StockAdjustment.Value=0 AND
Fields!ClosingStock.Value=0,
0,
1
)
) = 0
This is essentially a fancy way of counting the number of rows in which any field is not zero. If every field is zero for every row in the group then the expression returns true and the row is hidden.
Here is an example that should give you some idea..
=IIF(First(Fields!Gender.Value,"vw_BrgyClearanceNew")="Female" and
(First(Fields!CivilStatus.Value,"vw_BrgyClearanceNew")="Married"),false,true)
I think you have to identify the datasource name or the table name where your data is coming from.

Returned ID from SELECT statement

I use in my Project the IfExistsTable function; in order to see the existence of a table.
For this purpose I use the Select statement as follows.
MASQLComm = New SqlCommand("SELECT COUNT(*) AS [RecCount] From sys.tables WHERE name Like '%" & tName & "%'", SQLConn)
RecCount = CInt(MASQLComm.ExecuteScalar)
After that I take the number which returned in RecCount. Until now the numbers was 1 and 0
And so I was turn the numbers in True or False.
Now suddenly the returned number is 2 which I can’t understand what it means.
Count return the number of rows in the table. You should not expect it to be 0 or 1 only.
You can argue that there can't be more then one table with one name, but the problem is that your query uses like '%TableName%'. So if you have table MyTable and BestTable, and you want to check if Table exits, the result of count will be 2, although there are is no table with such name.
You could update the select statement to look like this:
select case when exists(select * from sys.tables where name = 'TableName') then 1 else 0 end
The number represents the number of tables that match your like statement. For example, if you have the tables
Widgets
Products
WidgetsInProducts
And pass "Widgets" into your query, it's going to match both the table "Widgets" and "WidgetsInProducts". This is not the behavior you want.
To resolve this you need to do an exact match instead of a like as #Alex Aza demonstrated in his answer.
hi Lefteris Gkinis
if you do not want to change your query you can check your RecCount variable accordingly
say
if(RecCount == 0)
{
// code what you were using for false condition
}
else
{
// you got atleast one record
// and in RecCount you have number of matching rows
}
by this kind of code you are able to show matched row count also.

Decrement-or-delete in SQL

In SQL, I've got a table that maps token=>count; it's a dict where the default value is 0. If I want to increment a token, I can say:
insert into my_table (token, count)
values (my_token, 1)
on duplicate key update count = count + 1;
and if a token doesn't exist yet, it's inserted with count=1. Nifty.
Is there a similarly easy way to do the opposite in SQL, i.e., "given a token, decrement its count, and if count becomes 0 then just remove the record entirely"? I can think of longer ways to do it, but nothing as concise as the above.
My advice is to use transactions as follows (my SQL is a bit rusty but you should get the idea):
-- begin transaction
update my_table set count = count - 1 where id = '7'
delete from my_table where id = '7' and count = 0
commit
This will ensure the atomicity of the decrement-and-delete operation.
However, one other possibility you may want to consider - don't remove it at the point where it reaches zero. Since you say the default value is zero anyway, just leave the row in there with a value of 0.
Of course, your queries will need to change to adapt to that. If you have one that lists active tokens, it will change from:
select token from my_table
to:
select token from my_table where count > 0
The decrement SQL in that case must be careful not to push the token count down to -1, so it would become:
update my_table set count = count - 1 where id = '7' and count > 0
That simplifies your SQL at the decrement time. If you still want those rows with zero-count to disappear, you could have another process that runs periodically to sweep them all up:
delete from my_table where count = 0
That's just some alternatives to consider - if you really want them gone at the exact time their count reaches zero, then use the transaction method above.
You want triggers. (I take it this is MS SQL).
Um, wouldn't the answer be the obvious:
insert into my_table (token, count)
values (my_token, 0)
on duplicate key update count = count - 1;