Get average of fields - sql

In this SQL statement:
select (ISNULL(Tbl1.Bromod,0) + ISNULL(Tbl1.Bromoform,0) +
ISNULL(Tbl1.Chlor,0) + ISNULL(Tbl1.Dibromoc,0)) / 4 )
from TblTruck
I'd like to dynamically change the value that is 4 currently to be the number of values that are NOT NULL.
What I am trying to do is to get the average ignoring NULL entries.
Say if Bromod is NULL and the others are not BULL, I would then divide by 3, as 3 actually have values.

select (
ISNULL(Tbl1.Bromod,0) + ISNULL(Tbl1.Bromoform,0) + ISNULL(Tbl1.Chlor,0) + ISNULL(Tbl1.Dibromoc,0)
)
/ ISNULL(
NULLIF(
CONVERT(INT,CONVERT(BIT,ISNULL(Tbl1.Bromod,0))) + CONVERT(INT,CONVERT(BIT,ISNULL(Tbl1.Bromoform,0))) + CONVERT(INT,CONVERT(BIT,ISNULL(Tbl1.Chlor,0))) + CONVERT(INT,CONVERT(BIT,ISNULL(Tbl1.Dibromoc,0)))
,0
)
,1
)
from TblTruck Tbl1
So,neat trick, all #s other than zero convert as a true when cast as a bit. So, NULLs and 0's become zero and all other values become 1. Sum together and that gives you what you are looking for. This solution also handles a divide by zero issue that would arise if all values were null/zero.

Related

Does the SQL CASE statement treat variables differently from columns?

I have the following code in a stored procedure and am trying to conditionally format a calculated number based on its length (if the number is less than 4 digits, pad with leading zeros). However, my case statement is not working. The "formattedNumber2" result is the one I'm looking for.
I'm assuming the case statement treats the variable strangely, but I also don't know of a way around this.
DECLARE #Number int = 5
SELECT
CASE
WHEN (LEN(CONVERT(VARCHAR, #Number)) > 4)
THEN #Number
ELSE RIGHT('0000' + CAST(#Number AS VARCHAR(4)), 4)
END AS formattedNumber,
LEN(CONVERT(VARCHAR, #Number)) AS numberLength,
RIGHT('0000' + CAST(#Number AS VARCHAR(4)), 4) AS formattedNumber2
I get the following results when I run the query:
formattedNumber numberLength formattedNumber2
-------------------------------------------------
5 1 0005
SQL DEMO
The problem is you are using different data type on your case , integer and string. So the CASE stay with the first type he find and convert the rest.
CASE WHEN (LEN(convert(VARCHAR, #Number)) > 4) THEN convert(VARCHAR, #Number)
This can be done a lot easier with format() since version 2012.
format(n,
'0000')
And that would also handle negative values, which your current approach apparently doesn't.
Prior 2012 it can be handled with basically replicate() and + (string concatenation).
isnull(replicate('-',
-sign(n)), '')
+
isnull(replicate('0',
4
-
len(cast(abs(n) AS varchar(10)))
),
'')
+
cast(abs(n) AS varchar(10))
(It targets integer values, choose a larger length for the varchar casts for bigint.)
db<>fiddle

How to auto generate a ID with random numbers in sql server

For example I had a column named 'ID'
I want to get the output as
ID
---
ABCXX708
ABCXX976
ABCXX654
ABCXX081
In short ABCXX should be common for every row but the remaining 3 numbers should be random and integer..
with t (n) as (select 0 union all select n+1 from t where n <100)
select 'ABC'
+ format(n,'00')
+ cast(cast(rand(cast(newid() as varbinary(100)))*10 as int) as char(1))
from t
Alternative solution
with t (n) as (select 0 union all select n+1 from t where n <100)
select 'ABC'
+ right ('0' + cast(n as varchar(2)),2)
+ cast(cast(rand(cast(newid() as varbinary(100)))*10 as int) as char(1))
from t
You can write like this
select 'ABCXX'+CAST(FLOOR(RAND()*(1000-100)+100) as varchar(3)) 'id'
With the RAND() function you can get Random numbers. And For the 'ABCXX' you can follow your previous logic.
SELECT CAST(RAND()*10.00 AS INT)
The above RAND() function will give values between 0.0 to 1.0 in decimals every time you hit the Statement. To make it for a single digit Multiply with 10 and Cast it to INT to remove the next decimal values.
Reference " MSDN
Since SQL Server 2012 you have FORMAT function and SEQUENCE object. Hence the below query will work.
First you need to create a Sequence object.
CREATE SEQUENCE DemopSeq
START WITH 1
INCREMENT BY 1;
Then the following query will generate results as per your requirement.
SELECT CONCAT('ABC',FORMAT(NEXT VALUE FOR DemopSeq, '00'),ABS(Checksum(NewID()) % 10))
Hope this helps.

SQL SELECT statement with Cast, LPad and Max

Are there any issues with this select statement ??
SELECT SUBSTR(FIELD_A,10,3) as MOVID,
MAX(LPAD((CAST(SUBSTR(FIELD_A,-3,3) as INT) + 1 ), 3, 0)) as NEXTMOVID
FROM ...
The field is a VARCHAR2.
I want to maintain 3 characters(which are numbers) and add 1 and concatenate with another varchar2
retrieve a portion of the FIELD_A
convert is to an integer
add 1
Left Pad it to 3 characters with 0
Grab the MAX
Later on I concatenate with another field
Wondering if there was a better way to do this ??
As I understand, you need following:
SELECT SUBSTR(FIELD_A,10,3) as MOVID,
to_char(to_number(SUBSTR(FIELD_A, -3, 3)) + 1), '000') as NEXTMOVID
FROM ...

Having an issue with select max

I have a column that has entries such as 86D12345, 86A12345, etc. I need to be able to do 2 things:
Select MAX value of this column
Add 1 to get the next number
This column is nvarchar, so I assume I will have to utilize the substring function plus the select MAX, but cannot seem to get the results. Example is when I run this query:
select substring(convert(numeric(5,0), certno),4,len(certno))+1 from maxcertno
I get:
Argument data type numeric is invalid for argument 1 of substring function.
Same error with cast
Any ideas?
Assuming the format if fixed like nn N nnnnn (without the blanks).
This gives the next value (12346):
cast(substring(certno, 4, len(certno)) as int) + 1
And this gives the whole string incremented by 1 (86D12346):
left(certno, 3) + cast(cast(substring(certno, 4, len(certno)) as int) + 1 as nvarchar(50))
With the max function:
select
cast(substring(max(certno), 4, len(max(certno))) as int) + 1,
left(max(certno), 3) + cast(cast(substring(max(certno), 4, len(max(certno))) as int) + 1 as nvarchar(50))
from YourTable
The last is probably not a good solution in that it's repeating max all over the query. Better to get the max value first and then apply the logic. Or maybe make it a function or stored proc.

Remove trailing zero from decimal number

I have a one database table field called Amount which type is decimal(18,6). so it is stored in database up to 6 decimal points like 9.786534 But while retrieving that field using select query i have to take care like following
Remove trialling zero e.g if number is 9.230000 then result is only 9.23
If decimal points are all zero then only remove only four trialling zero e.g If number is 9.000000 then result is 9.00
Result is up to 2 decimal point if there are trialling zero.
If we write simple query like
select TOP 1 Amount From EmployeeMaster
then it gives 9.230000
but my intension is to remove trailing zero..
Please help me..
It works for removing trailing zeros, but I am still not able to convert 9 to 9.00 in this method.
Declare #myvalue varchar(50),
#Price Varchar(50)
Set #Price = '9.230000'
set #Myvalue = reverse(substring(#Price,patindex('%.%',#Price)+1,len(#Price)))
SELECT
case
When patindex('%.%[1-9]%',#price) = 0 Then
substring(#price,1,patindex('%.%',#price)-1)
else
substring(#price,1,patindex('%.%',#price)-1) + '.' + Reverse(substring(#Myvalue,patindex('%[1-9]%',#Myvalue),len(#Myvalue)))
END
Coming from decimal(18,6) you could do...
select cast(Amount as decimal(18,2))
Most databases that support the CAST function will round the number while converting it. On SQLServer this is what I would do if I wanted rounding.
If what you actually want is a string with only two digits after the decimal then you could
select cast((Amount as decimal(18,2)) as nvarchar)
nvarchar is SQLServer's variable length unicode type. Databases do not agree much on string types. Your database may have a different one. The rest of that sql is ANSI standard. Not all dbs support that either but many do.
This should work
SELECT CAST(REPLACE(RTRIM(REPLACE(CAST(CAST(33.9082976 AS DECIMAL(38,8)) AS NVARCHAR(256)),'0',' ')),' ','0') AS FLOAT)
Does this work?
select TOP 1 ROUND(Amount, 2) From EmployeeMaster
TRY below mentioned code.
SELECT TOP 1 CONVERT(DECIMAL(10,2),Amount) From EmployeeMaster
Hope it will work as expected.
An alternative approach:
1) convert the decimal to a string;
2) split the string into 2 parts, separating the last 4 characters from the rest of the string;
3) remove trailing zeros from the last 4 characters;
4) concatenate the two parts back.
WITH data (V) AS (SELECT CAST(9.786534 AS decimal(18,6))
UNION ALL
SELECT CAST(9.78653 AS decimal(18,6))
UNION ALL
SELECT CAST(9.7800 AS decimal(18,6))
UNION ALL
SELECT CAST(9.7 AS decimal(18,6))
UNION ALL
SELECT CAST(9.00000 AS decimal(18,6))
)
, AsString (V) AS (SELECT CAST(V AS varchar) FROM data)
, Split (L, R) AS (SELECT LEFT(V, LEN(V) - 4), RIGHT(V, 4) FROM AsString)
, Adjusted AS (SELECT L,
REPLACE(RTRIM(REPLACE(R, '0', ' ')), ' ', '0') AS R
FROM Split)
SELECT Result = L + R FROM Adjusted
The output of the above script is:
Result
--------
9.786534
9.78653
9.78
9.70
9.00
I guess using patindex in your case:
CASE WHEN FLOOR(Amount) <> CEILING(Amount) THEN
LTRIM(SUBSTRING(STR(Amount, 18, 6), 1, LEN(STR(Amount, 18, 6)) - PATINDEX('%[^0]%', REVERSE(str(Amount, 18, 6))) + 1))
ELSE STR(Amount,18,2)
END
for a decimal(18,6) field this should work:
select trim(to_char(Amount, '999999999999999999.99')) from EmployeeMaster
(at least for Oracle, not sure about other types)