sql calculate column value then order by it - sql

I have the sql below, and I then calculate one of the fields (market_cap) within the application code not the sql. I'd like to calculate it then order the records based on the top 7 calculated from it.
Proposed-ish Sql:
SELECT TOP 7 'market_cap' as [market_cap_calc] ??, [tradingcode],[last],[prvclose],[currentsharesonissue]
FROM [PricesCurrent]
ORDER BY tradingcode DESC
Asp code for field market_cap:
If Not IsNull(rs("last")) Then
marketcap = 0
If Not IsNull(rs("currentsharesonissue")) And Cdbl(rs("last")) <> 0 Then marketcap = (CDbl(rs("last")) * CDbl(rs("currentsharesonissue")))/1000000.0
End If
If marketcap = 0 And Not IsNull(rs("prvclose")) Then
If Not IsNull(rs("currentsharesonissue")) And CDbl(rs("prvclose")) > 0 Then marketcap = (CDbl(rs("prvclose")) * CDbl(rs("currentsharesonissue")))/1000000.0
End If
So basically it needs to check if last or prvclose is empty and then multiply either one by currentsharesonissue to get marketcap, and then get the top 7 rows based on that marketcap figure, how do I go about this? make a temporary table first?

You can do this with coalesce and a cte
WITH CTE AS(
SELECT
coalesce([last],[prvclose],0) * currentsharesonissue as CalculatedColumn
FROM [PricesCurrent])
select top 7 * from cte order by CalculatedColumn desc
COALESCE() is going to take the first NOT NULL value and multiply it by the currentsharesonissue column. Then, we just get the TOP7 as you stated, in DESCENDING order (assumed).

Related

How to check max from range in cursor?

I have a problem with transferring an Excel formula to SQL. My excel formula is: =IF(P2<(MAX($P$2:P2));"Move";"").
The P column in excel is a sequence of numbers.
a | b
------
1
2
7
3 MOVE
4 MOVE
8
9
5 MOVE
10
You can find more example on this screenshot:
I created a cursor with a loop but I don't know how to check max from range.
For example when I iterate for fourth row, I have to check max from 1-4 row etc.
No need for a cursor and a loop. Assuming that you have a column that defines the ordering of the rows (say, id), you can use window functions:
select t.*,
case when a < max(a) over(order by id) then 'MOVE' end as b
from mytable t
One option would be using MAX() Analytic function . But in any case, you'd have an extra column such as id for ordering in order to determine the max value for the current row from the first row, since SQL statements represent unordered sets. If you have that id column with values ordered as in your sample data, then consider using
WITH t2 AS
(
SELECT MAX(a) OVER (ORDER BY id ROWS BETWEEN
UNBOUNDED PRECEDING
AND
CURRENT ROW) AS max_upto_this_row,
t.*
FROM t
)
SELECT a, CASE WHEN max_upto_this_row > a THEN 'Move' END AS b
FROM t2
ORDER BY id;
Demo

Get 2nd from string in SQL

I have a requirement in SQL where I am getting a string and need to get the top 2nd row.
I am using SQL version 2014
I have a string which I am to spitting using the character 'M'
string is as follows: 3908K88513K1992K898593M
if I pass input: 88513 I need to get the output as 898593
Another example is
string: 24572K12345K10981K19809K
if the input is 19809 output should be: 12345
I have tried below code but it is failing at 2nd input example string:
SELECT TOP 1 T.*
FROM (
SELECT TOP 2 *
FROM splitfunction((
SELECT number
FROM name
WHERE id = 100709
), 'K')
) AS T
ORDER BY 1 DESC;
As Jarlh mentioned in the comments, instead of using TOP, use OFFSET and FETCH:
SELECT ss.* --This should be your columns
FROM dbo.contact c
CROSS APPLY dbo.dba_splitstring(c.structureno,'M') ss
WHERE c.recno = 100719
ORDER BY {????} --Your ORDER BY was missing in your query
OFFSET 1 ROWS FETCH NEXT 1 ROWS ONLY;
I've also reformulated your query, as all those subqueries weren't necessary.

How to subtract the content of a column of two rows

I have a table like this
and I want to return the difference between the two rows
SQL tables represent unordered sets. There is no ordering, unless a column specifies the ordering.
So, you can get the two values using MAX() and MIN(). This should do what you want:
select max(nbaction) - min(nbaction)
from t;
EDIT:
Given your actual problem, you have multiple choices. Here is one:
SELECT (SELECT nbaction
FROM analyse_page_fait
WHERE operateurdimid = 2
ORDER BY datedimid DESC
FETCH FIRST 1 ROW ONLY
) -
(SELECT nbaction
FROM analyse_page_fait
WHERE operateurdimid = 2
ORDER BY datedimid DESC
OFFSET 1
FETCH FIRST 1 ROW ONLY
) as diff

Using returned variables in a SQL Server query

I am using SQL Server 2012 and I have a query which returns two columns, the Item number and the Row number of that item in the query:
Row Item
--------------
1 1234
2 5632
3 4213
4 0912
Before I run the query I will know that I am only interested in the row containing Item 5632 and X number of rows following the one containing item 5632 (in this case lets just say rows 2 and 3). However, I will not know ahead of time what row Item 5632 is in.
I would like to somehow say
Where Row >= Row of Item 5632
And Row <= Row of Item 5632 + X
Is this possible to do? Thank you all!
Supposing the query you have now is SELECT RowNo, Item FROM Tbl, the following query can replace it and do what you want:
DECLARE #Item = 5632
DECLARE #ItemRowNo = SELECT RowNo FROM Tbl WHERE Item = #Item
DECLARE #Qty = 2
SELECT RowNo, Item
FROM Tbl
WHERE Item >= #ItemRowNo
AND Item < (#ItemRowNo + #Qty)
ORDER BY RowNo
If you give me your actual current query, I can update this answer to reflect it.
You may choose to declare less things than what I did if they will be constant, but I'm guessing that you will in fact be SELECTing them from elsewhere.
More than one way to do this, im more accustomed to nested queries
Nested select statement in SQL Server
SQL nested query in SQL server
More specifically:
SELECT TOP 3 a.row, a.item FROM tableA a
WHERE a.row >= (SELECT row FROM tableA WHERE item = 5632)
ORDER BY a.row
TOP doesnt worry about actual value of ROW, just limits number of retrieved records
http://www.w3schools.com/sql/sql_top.asp
http://www.w3schools.com/sql/sql_where.asp
http://www.w3schools.com/sql/sql_orderby.asp

How to limit rows to where SUM of a column equals to certain value and go to next row Oracle

Based on my question here, I have managed to get the answer.. but then a new problem arise that I need to display it like this :
Firstly, here is the studyplan table
So now, on the first run, it will display like this if I want to get the rows until SUM of Credit column equal to 18 :
But, then on the second run, I want it to be displayed like this if I want to get the rows until the SUM of Credit column equal to 21 :
How I want it to SUM the column at the next row? Do I have to make 2 SQL statement?
Here is the success code from the first run :
SELECT * FROM
(SELECT t.*,
SUM(t.credit) OVER (PARTITION BY t.matricsno ORDER BY t.sem, t.subjectcode)
AS credit_sum
FROM studyplan t)
WHERE credit_sum <= 17 AND matricsno = 'D031310087';
Thank you for your response and time.
Here is the link, How to limit rows to where SUM of a column equals to certain value in Oracle
It's a bit of an odd requirement. But, yes, if you want 2 different result sets, you'll need separate 2 SQL statements. But for each additional statement, you would only need to tweak your condition on credit_sum.
For instance, if for your 1st query you want to get the rows up to when the credit sum reaches 18, you would do:
select *
from (select t.*,
sum(t.credit) over (order by t.sem, t.subjectcode) as credit_sum
from studyplan t
where t.matricsno = 'D031310087')
where credit_sum <= 18
order by sem, subjectcode
For your 2nd query, you say you want the rows where the credit sum reaches 21, but ignoring the rows returned by the 1st query. Another way to express that requirement is to return the rows for which the cumulative credit sum is between 19 and 39 (inclusive). So then, it simply becomes a matter of modifying the filter on credit_sum to use a between condition:
select *
from (select t.*,
sum(t.credit) over (order by t.sem, t.subjectcode) as credit_sum
from studyplan t
where t.matricsno = 'D031310087')
where credit_sum between 19 and 39
order by sem, subjectcode