Difference between 2 numbers and return a % - sql

I'm Looking to see if I can return a % from the following, but it need finishing.
SELECT COUNT(*) FROM VEHICLES_FW
WHERE ARCHIVE_STATUS_FW = 'N'
AND LOCATION_CODE_FW IN ('L0078')
This brings me back the amount of vehicle on this location. I know that the location has a limit of 180.
How do I write in so it works out that the % is 31%?

Ok, how i don't know what SQL variant you use, I write my response how I'll write on SQL Server.
If you want % respect of limit (180)
DECLARE #PERCENTAGE DECIMAL --Or INT if you prefer it
SET #PERCENTAGE = (SELECT COUNT(*) FROM VEHICLES_FW
WHERE ARCHIVE_STATUS_FW = 'N'
AND LOCATION_CODE_FW IN ('L0078')) * (100 / 180)
RETURN PERCENTAGE;
If you want % respect all cars
DECLARE #PERCENTAGE DECIMAL --Or INT if you prefer it
DECLARE #TOTAL DECIMAL --Or INT if you prefer it
SET #TOTAL = (SELECT COUNT(*) FROM VEHICLES_FW)
SET #PERCENTAGE = (SELECT COUNT(*) FROM VEHICLES_FW
WHERE ARCHIVE_STATUS_FW = 'N'
AND LOCATION_CODE_FW IN ('L0078')) * (100 / 180)
RETURN PERCENTAGE;

Related

Calculation using SQL server

Formula used
This is the formula that I used to calculate
Expressed as a single equation:
eGFR = 142 x min(Scr/κ, 1)α x max(Scr/κ, 1)-1.200 x 0.9938Age x 1.012 [if female]
where:
Scr = serum creatinine in mg/dL
κ = 0.7
α = -0.329
min(Scr/κ, 1) is the minimum of Scr/κ or 1.0
max(Scr/κ, 1) is the maximum of Scr/κ or 1.0
Age (years)
Code that I tried
select
ROUND(141 * power(min(cast(40 as float) / 0.7 ) ,-0.329) *
power(max( cast(40 as float) / 0.7 * 1) ,- 1.209) * 0.993 *
cast(42 as float) * 1.018 ,2) as kidney
Correct answer should be 123.
Any clue what I am missing in the query?
Don't use MIN and MAX, those are aggregate (GROUP BY) functions. It would be good if SQL Server had GREATEST and LEAST functions, but it doesn't yet.
IIF(a < b, a, b) is LEAST(a,b).
IIF(a > b, a, b) is GREATEST(a,b).
Don't sweat the CASTs.
Make no assumptions about operator precedence ( x before +, etc). Use parentheses.
Here's a rewrite of what I believe your formula should be. But I'm not getting the right answer yet either.
DECLARE #Scr AS INT = 40;
DECLARE #k AS FLOAT = 0.7;
DECLARE #a AS FLOAT = -0.329;
DECLARE #age AS INT = 42;
DECLARE #gender AS VARCHAR(MAX) = 'female';
DECLARE #factor AS FLOAT = CASE WHEN #gender = 'male' THEN 1.0 ELSE 1.012 END;
SELECT 142
+ (IIF(1 < #Scr/#k, 1, #Scr/#k) * #a)
* (IIF(1 > #Scr/#k, 1, #Scr/#k))
- (1.2 * 0.993 * #age * #factor);
I obviously misunderstood your formula, but this should get you started. Here's a fiddle.
According to this site your equation is kinda wrong. Please be sure to add ^ to display the "to the power of".
DECLARE #Scr AS FLOAT = 40.0;
DECLARE #gender AS VARCHAR(10) = 'female';
DECLARE #age AS SMALLINT = 42;
DECLARE #k AS FLOAT = CASE WHEN #gender = 'male' THEN 0.9 ELSE 0.7 END;
DECLARE #a AS FLOAT = CASE WHEN #gender = 'male' THEN -0.302 ELSE -0.241 END;
DECLARE #factor AS FLOAT = CASE WHEN #gender = 'male' THEN 1.000 ELSE 1.012 END;
SELECT 142 * POWER(IIF(1 < (#Scr/#k), 1, #Scr/#k), #a)
* POWER(IIF(1 > (#Scr/#k), 1, #Scr/#k), -1.200)
* POWER(0.9938, #age)
* #factor;
Also this result is correct since it is calculated in mg/dl and your expected value is in umol/l
Here is another website (it may be german, but it should do the trick)

SQL: Use table from table valued function

I'm sure there is a better way of doing this as I am running the same Table Valued Function several times, is there a way to get the table from the TVF just once and then run the queries against it to set my variables?
DECLARE #RUNS INT
DECLARE #WON INT
DECLARE #PERC FLOAT
SET #RUNS = (SELECT COUNT(*) FROM tvf_horse_going('Allow Me', 'HEAVY'))
SET #WON = (SELECT COUNT(*) FROM tvf_horse_going('Allow Me', 'HEAVY') WHERE PosNum = '1')
SET #PERC = (#WON * 100) / #RUNS
SELECT #RUNS As Runs, #WON As Won, #PERC As Perc
select
#RUNS = count(*),
#WON = sum(case when PosNum = 1 then 1 else 0 end)
from tvf_horse_going('Allow Me', 'HEAVY')
set #PERC = (#WON * 100) / #RUNS
SELECT runs
, won
, won * 100.0 / runs As perc
FROM (
SELECT Count(*) As runs
, Sum(CASE WHEN PosNum = 1 THEN 1 ELSE 0 END) As won
FROM tvf_horse_going('Allow Me', 'HEAVY')
) As results
Note the * 100.0. This is a quick and easy way to avoid using integer math. Other [less lazy] methods would include: Cast(won As decimal(5,2)) / Cast(runs As decimal(5,2)) or similar
You can also use hash table (temporary table).
DECLARE #RUNS INT
DECLARE #WON INT
DECLARE #PERC FLOAT
SELECT * INTO #TEMP FROM tvf_horse_going('Allow Me', 'HEAVY')
SET #RUNS = (SELECT COUNT(*) FROM #TEMP)
SET #WON = (SELECT COUNT(*) FROM #TEMP WHERE PosNum = '1')
SET #PERC = (#WON * 100) / #RUNS
SELECT #RUNS As Runs, #WON As Won, #PERC As Perc

How do I get an int

Seems like a simple question... but I am stumped.
declare #Total_User int
set #Total_User = 8
declare #Total int
set #Total = 12
declare #Number int
set #Number = (#Total_User / #Total) * 100
select #Number as 'Standard'
I am expecting 66, but my select comes out zero ??
What am I doing wrong?
The result of (#Total_User / #Total) is zero, as it is doing integer division.
You can multiply by 100 first, which gives the result that you expected:
set #Number = 100 * #Total_User / #Total
To get a rounded value rather than truncated, you would use floating point values and the round function:
set #Number = round(100.0 * #Total_User / #Total, 0)
This will give the result 67 rather than 66, as that is closer to the actual result 66.6666666666
Try:
set #Number = (#Total_User*100 / #Total)
Your division #Total_User / #Total is using integer arithmetic i.e. any remainder will be discarded, so that part of the expression will be 0.
To fix, write (1.0 * #Total_User / #Total) * 100. This promotes the operation to floating point.
You are doing integer arithmetic, that is why you see the 0, make at least one of the operand as float and you will see the correct result like:
declare #Total float
Or you can cast one operand as float like:
et #Number = (CAST(#Total_User as float) / #Total) * 100
Your current code is doing:
8 / 12
Which would result in 0.666666666667, but since both of your operands are of type int the calculation is performed using int type, thus result in 0 and not 0.66666666667.
You get 0 because you are doing integer division of #Total_User and #Total.
You have two options to get the correct result:
First multiply Ttotal_User by 100 and then divide by #Total:
set #Number = (#Total_User * 100) / #Total
Cast #Total_User and #Total to floating point before making the division:
set #Number = (cast(#Total_User as float) / cast(#Total as float)) * 100
declare #Total_User float,
#Total float,
#Number float
SET #Total_User = 8
SET #Total = 12
SET #Number = #Total_User / #Total * 100
select CAST(#Number AS INT) AS 'Standard'
This will give you 66

how to truncate a number in sybase ASE?

http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.infocenter.dc38151.1540/doc/html/san1278453173757.html
The functions TRUNCATE and TRUNCNUM are not supported in Adaptive Server Enterprise.
Does anyone know another way of doing this in ASE?
Thanks
I know these ways:
select Number = floor ( 455.443 )
select Number = cast ( 455.443 as int )
select Number = convert ( int, 455.443 )
select Number = 455.443 - ( 455.443 % 1 )
How about using the Floor function? It essentially does the same thing, and is supported in ASE.
This is an old question, but I did this a few days ago to mimic the "truncnum" function described in the link above.
create function custom_truncnum(#numberToTruncate float, #decimalPlaces int)
returns float
AS
declare #tenToTheXPower float;
declare #leftSideOfDecimal float;
declare #returnVal float;
set #tenToTheXPower = power(10, ABS(#decimalPlaces);
set #leftSideOfDecimal = FLOOR(#numberToTruncate);
if (#decimalPlaces <= 0)
set #returnVal = FLOOR(#numberToTruncate / #tenToTheXPower) * #tenToTheXPower;
else
set #returnVal = #leftSideOfDecimal + (FLOOR(#numberToTruncate - #leftSideOfDecimal) * #tenToTheXPower) / #tenToTheXPower);
return #returnVal;
GO
Now you should be able to do this in Sybase ASE:
SELECT dbo.custom_truncnum(345.567, 2)
345.56
SELECT dbo.custom_truncnum(345.562, 2)
345.56
SELECT dbo.custom_truncnum(345.567, -1)
340
SELECT dbo.custom_truncnum(345.567, -2)
300
SELECT dbo.custom_truncnum(345.567, 0) --This is the same as FLOOR(345.567)
345

SQL Data Sampling

We have had a request to provide some data to an external company.
They require only a sample of data, simple right? wrong.
Here is their sampling criteria:
Total Number of records divided by 720 (required sample size) - this gives sampling interval (if result is a fraction, round down to next whole number).
Halve the sampling interval to get the starting point.
Return each record by adding on the sampling interval.
EXAMPLE:
10,000 Records - Sampling interval = 13 (10,000/720)
Starting Point = 6 (13/2 Rounded)
Return records 6, 19 (6+13), 32 (19+13), 45 (32+13) etc.....
Please can someone tell me how (if) something like this is possible in SQL.
If you have use of ROW_NUMBER(), then you can do this relatively easily.
SELECT
*
FROM
(
SELECT
ROW_NUMBER() OVER (ORDER BY a, b, c, d) AS record_id,
*
FROM
yourTable
)
AS data
WHERE
(record_id + 360) % 720 = 0
ROW_NUMBER() gives all your data a sequential identifier (this is important as the id field must both be unique and NOT have ANY gaps). It also defines the order you want the data in (ORDER BY a, b, c, d).
With that id, if you use Modulo (Often the % operator), you can test if the record is the 720th record, 1440th record, etc (because 720 % 720 = 0).
Then, if you offset your id value by 360, you can change the starting point of your result set.
EDIT
After re-reading the question, I see you don't want every 720th record, but uniformly selected 720 records.
As such, replace 720 with (SELECT COUNT(*) / 720 FROM yourTable)
And replace 360 with (SELECT (COUNT(*) / 720) / 2 FROM yourTable)
EDIT
Ignoring the rounding conditions will allow a result of exactly 720 records. This requires using non-integer values, and the result of the modulo being less than 1.
WHERE
(record_id + (SELECT COUNT(*) FROM yourTable) / 1440.0)
%
((SELECT COUNT(*) FROM yourTable) / 720.0)
<
1.0
declare #sample_size int, #starting_point int
select #sample_size = 200
select top (#sample_size) col1, col2, col3, col4
from (
select *, row_number() over (order by col1, col2) as row
from your_table
) t
where (row % ((select count(*) from your_table) / #sample_size)) - (select count(*) from your_table) / #sample_size / 2) = 0
It's going to work in SQL Server 2005+.
TOP (#variable) is used to limit rows (where condition because of integers rounding might not be enough, may return more rows then needed) and ROW_NUMBER() to number and order rows.
Working example: https://data.stackexchange.com/stackoverflow/query/62315/sql-data-sampling below code:
declare #tab table (id int identity(1,1), col1 varchar(3), col2 varchar(3))
declare #i int
set #i = 0
while #i <= 1000
begin
insert into #tab
select 'aaa', 'bbb'
set #i = #i+1
end
declare #sample_size int
select #sample_size = 123
select ((select count(*) from #tab) / #sample_size) as sample_interval
select top (#sample_size) *
from (
select *, row_number() over (order by col1, col2, id desc) as row
from #tab
) t
where (row % ((select count(*) from #tab) / #sample_size)) - ((select count(*) from #tab) / #sample_size / 2) = 0
SQL server has in-built function for it.
SELECT FirstName, LastName
FROM Person.Person
TABLESAMPLE (10 PERCENT) ;
You can use rank to get a row-number. The following code will create 10000 records in a table, then select the 6th, 19th, 32nd, etc, for a total of 769 rows.
CREATE TABLE Tbl (
Data varchar (255)
)
GO
DECLARE #i int
SET #i = 0
WHILE (#i < 10000)
BEGIN
INSERT INTO Tbl (Data) VALUES (CONVERT(varchar(255), NEWID()))
SET #i = #i + 1
END
GO
DECLARE #interval int
DECLARE #start int
DECLARE #total int
SELECT #total = COUNT(*),
#start = FLOOR(COUNT(*) / 720) / 2,
#interval = FLOOR(COUNT(*) / 720)
FROM Tbl
PRINT 'Start record: ' + CAST(#start as varchar(10))
PRINT 'Interval: ' + CAST(#interval as varchar(10))
SELECT rank, Data
FROM (
SELECT rank()
OVER (ORDER BY t.Data) as rank, t.Data AS Data
FROM Tbl t) q
WHERE ((rank + 1) + #start) % #interval = 0