I have a table with salary of multiple employees.
I need to calculate score for these employees using a derived number (mean and stddev) and include it as a new column.
I know I can do this in the select statement, but if I wanted see if I can use variables.
So that changes can be made dynamically. I am new to SQL and just trying to learn things here.
declare #Weight int,
#weight2 int,
#Mean int,
#StdDevn int,
#Variance int
set #Weight = 30
set #weight2 = (POWER(#weight,2)/100)
SELECT #Mean = AVG(salary) FROM [live].[dbo].[salary]
SELECT #StdDevn = STDEV(salary) FROM [live].[dbo].[salary]
SELECT #Variance = (POWER(#StdDevn,2)/100)
-- I should include some code here so that the above variable are passed to below query
SELECT * FROM [live].[dbo].[salary], (([salary]-#Mean)/#StdDevn)
Error:
Must declare variable #Mean, Incorrect syntax near '-'.
The problem you have is how you are trying to select.
The variable #Mean is declared and it would work if the final select would be something like below:
SELECT *,
(([salary]-#Mean)/#StdDevn) as SomeOtherCol
FROM [live].[dbo].[salary]
The SomeOtherCol will be then shown as the last column of your result set.
Related
I have some specific set of values that I want to filter on a column, I don't want to do an 'in' clause in SQL Server. I want to use loop to pass in different set of values each time.
For example if there is a name column in my data, and I want to run query 5 times with different filter value.
Please look at the loop query attached below.
DECLARE #cnt INT = 1;
WHILE #cnt < 94
BEGIN
SELECT Name, COUNT(*) AS Number_of_Names
FROM Table
WHERE name IN ('John')
AND value IS NOT NULL
GROUP BY Name
SET #cnt = #cnt + 1;
END;
I want to pass in different values under 'name' column at each loop like john in the case above, then mary in the next loop likewise based on set of values I pass in the variable like #values = John,Mary,Nicole,matt etc..
Considering the comments on your question, this should give you an idea on how to achieve a solution without using loops and still get all the names even when the name is not present on the table.
SELECT Name,
COUNT(value) AS Number_of_Names --Only count when value is not null
FROM (VALUES('John'), ('Mary'), ('Nicole'), ('Matt'))Names(name) --This can be replaced by a table-valued parameter or temp table.
LEFT JOIN Table t ON Names.name = t.name
--WHERE name IN ('John') /*No longer needed*/
--AND value IS NOT NULL /*Removed this because it would make the OUTER JOIN behave as an INNER JOIN*/
GROUP BY Name;
I'd like to update fields while referring to a dynamic column.
The goal is to automate a process because each month the column to refer to changes.
For example it's like having different columns like month1, month2, month3 until month24. Each month, only 1 column needs to be updated but it's a running number that is calculated in another table.
So my question is how to make the query dynamic so that every month i only update the column number that i want and not the other one.
I tried the script below but the following issue comes up
Error converting data type varchar to float.
DECLARE #PromoMonthNumber VARCHAR(60)
DECLARE #PromoMonth VARCHAR(600)
SET #PromoMonthNumber = (SELECT CurrentDemandIndex FROM RidgeSys) --This refer to a number that change all the time
SET #PromoMonth = 'SELECT ABC.PromotionHistory' + #PromoMonthNumber
UPDATE ABC
SET #PromoMonth = table2.promotionhistory
FROM ABC
INNER JOIN (
SELECT Article.code as code, sum(ROUND(#PromoMonth,0)) as promotionhistory
FROM Article
INNER JOIN ABC ON DEF.articlecode = ABC.Articlecode
) as table2
ON ABC.articlecode = table2.code)
Here is your issue:
SELECT Article.code as code, sum(ROUND(#PromoMonth,0)) as promotionhistory
Since #PromoMonth is defined as VARCHAR, if the value is non-numeric, it will fail. Here is an example:
This works fine:
declare #x varchar(100) = '1';
select sum(round(#x,0));
Result:
1
This fails with same error above:
declare #x varchar(100) = 'x';
select sum(round(#x,0));
Result:
Msg 8114, Level 16, State 5, Line 3
Error converting data type varchar to float.
You need to check that the value is numeric before you do the calculation.
I created a database with NBA player statistics just to practice SQL and SSRS. I am new to working with stored procedures, but I created the following procedure that should (I think) allow me to specify the team and number of minutes.
CREATE PROCEDURE extrapstats
--Declare variables for the team and the amount of minutes to use in --calculations
#team NCHAR OUTPUT,
#minutes DECIMAL OUTPUT
AS
BEGIN
SELECT p.Fname + ' ' + p.Lname AS Player_Name,
p.Position,
--Creates averages based on the number of minutes per game specified in #minutes
(SUM(plg.PTS)/SUM(plg.MP))*#minutes AS PTS,
(SUM(plg.TRB)/SUM(plg.MP))*#minutes AS TRB,
(SUM(plg.AST)/SUM(plg.MP))*#minutes AS AST,
(SUM(plg.BLK)/SUM(plg.MP))*#minutes AS BLK,
(SUM(plg.STL)/SUM(plg.MP))*#minutes AS STL,
(SUM(plg.TOV)/SUM(plg.MP))*#minutes AS TOV,
(SUM(plg.FT)/SUM(plg.MP))*#minutes AS FTs,
SUM(plg.FT)/SUM(plg.FTA) AS FT_Percentage,
(SUM(plg.FG)/SUM(plg.MP))*#minutes AS FGs,
SUM(FG)/SUM(FGA) as Field_Percentage,
(SUM(plg.[3P])/SUM(plg.MP))*#minutes AS Threes,
SUM([3P])/SUM([3PA]) AS Three_Point_Percentage
FROM PlayerGameLog plg
--Joins the Players and PlayerGameLog tables
INNER JOIN Players p
ON p.PlayerID = plg.PlayerID
AND TeamID = #team
GROUP BY p.Fname, p.Lname, p.Position, p.TeamID
ORDER BY PTS DESC
END;
I then tried to use the SP by executing the query below:
DECLARE #team NCHAR,
#minutes DECIMAL
EXECUTE extrapstats #team = 'OKC', #minutes = 35
SELECT *
When I do that, I encounter this message:
Msg 263, Level 16, State 1, Line 5
Must specify table to select from.
I've tried different variations of this, but nothing has worked. I thought the SP specified the tables from which to select the data.
Any ideas?
Declaring the stored procedure parameters with OUTPUT clause means the values will be returned by the stored procedure to the calling function. However you are using them as input parameters, please remove the OUTPUT clause from both input parameters and try.
Also remove the SELECT * in your execute statement, it is not required, the stored procedure will return the data as it has the select statement.
I am trying to use the table variable #notified in a NOT IN where clause like this....
DECLARE #notified TABLE (DMT_ID INT)
INSERT INTO #notified
SELECT [DMT_ID]
FROM [dbo].[PU_Transaction]
WHERE [PU_TransactionStatus] = 3
SELECT * from #notified
SELECT [NRO_TRANSACCION]
FROM [dbo].[TRANSACCION]
WHERE [NRO_TRANSACCION] NOT in (#notified)
But I am getting this error in the last SELECT
Must declare the scalar variable "#notified".
What is wrong ? How can this be solved.
You need to use this:
SELECT [NRO_TRANSACCION]
FROM [dbo].[TRANSACCION]
WHERE [NRO_TRANSACCION] NOT IN (SELECT DMT_ID FROM #notified)
You need to put a SELECT statement in the NOT IN clause - not just a table variable name...
select x from y where x not in (select x from z)
You should have two selects to use a not in.
in my table the value is like this in field transectionNO is like
R1000891 R1000892 R1000893 ..... I want that last transactionNo means R1000893 as a result without R . So i can add R + last transactionNo + 1 in to create new transectionNo.
i used below query but sometime this query gives old value so it is creation error.
DECLARE #trnsectionNo varchar(50) ,
#RoundTotal varchar(50) ,
#transactionNo varchar(50)
SELECT top 1 #trnsectionNo = trans_no from Item_Receive ORDER BY trans_no DESC
SET #trnsectionNo= Substring(#trnsectionNo,2,10)
SET #RoundTotal= (ISNULL(#trnsectionNo,0) + 1)
SET #transactionNoNew = 'R'+#RoundTotal
thanks for your help .
Please try this query. I've also created a fiddle for demo:
http://sqlfiddle.com/#!6/e928b/6
Note that changes I made only included casting the substring as INT and applying MAX on it.
DECLARE #trnsectionNo INT ,
#RoundTotal varchar(50) ,
#transactionNoNew varchar(50)
SELECT #trnsectionNo = MAX(CAST(Substring(#trnsectionNo,2,10)AS INT)) from Item_Receive
SET #RoundTotal= (ISNULL(#trnsectionNo,0) + 1)
SET #transactionNoNew = 'R'+#RoundTotal
The problem you have is that you're not converting the number into int, so SQL Server can't do the +1. This is what you should be doing:
DECLARE #trnsectionNo varchar(50) ,
#transactionNoNew varchar(50)
SELECT top 1 #trnsectionNo = trans_no from Item_Receive ORDER BY trans_no DESC
if (##rowcount = 0) set #trnsectionNo = 'R0'
select #transactionNoNew = 'R'+convert(varchar(10), convert(int, Substring(#trnsectionNo,2,10)) + 1)
If you need to have zeros in the number, e.g. R000001 instead of R1, then you'll need to add more logic.
Try Using Stuff
select top 1 #trnsectionNo = trans_no from Item_Receive order by Stuff(trans_no,1,1,'') desc
I'm writing this as an answer as it's too long for a comment.
The other answers here will tell you how to fix your problem by converting your varchar to an int. They're correct within the scope of the question you asked, which in essence was "how do I make this piece of really unsafe code work (most of the time)?"
Why do I say your code is unsafe? Atomicity! If you have two calls to your query close together you will get duplicate numbers. Please read about Atomicity and related concepts here: http://searchsqlserver.techtarget.com/definition/ACID They are critical for writing safe DB Code!
If you want to continue with the code you have, and give yourself a hard life trying to make it safe, you would need to wrap the whole thing in a transaction and hold a lock on your table too. The transaction would also need to include the subsequent insert of your new ID number, which you don't include in your snippet.
But why use a varchar to hold an sequential transaction No. anyway? If you need it to show with a "R" in front that should be in your UI code.
If you want safe code with atomicity and an easy life, just use an int column with the identity attribute. See here for more info: http://www.sqlteam.com/article/understanding-identity-columns
If you need to get the new ID value back to your app, use the SCOPE_IDENTITY() function: https://msdn.microsoft.com/en-gb/library/ms190315(v=sql.110).aspx