Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I have the following SQL Server query that I would like to add order by clause. Can someone take a look at the QRY.
declare #variable int
set #variable = 0
UPDATE r_recipes_tmp
SET #variable = stepId = #variable + 1
I was trying the following with no luck.
declare #variable int
set #variable = 0
UPDATE r_recipes_tmp
SET #variable = stepId = #variable + 1
WHERE stepId IN (SELECT stepId
FROM r_recipes_tmp
WHERE recipename = 'test'
ORDER BY stepid DESC)
Thank you
It seems like you want to sort the rows in the descending order of stepId, then assign new consecutive values to stepId but this time in the ascending order, so essentially you want to reverse the order of rows if stepId was the sorting criterion. Or, using an example (which you haven't provided), turn a row set like this:
stepId someColumn
------ ----------
7 AAA
4 BBB
2 DDD
1 CCC
into this:
stepId someColumn
------ ----------
1 AAA
2 BBB
3 DDD
4 CCC
If that is indeed so and if you are using SQL Server 2005 or later version, you could use a CTE and the ROW_NUMBER() function like this:
WITH newIDs AS (
SELECT
stepId,
newStepId = ROW_NUMBER() OVER (ORDER BY stepId DESC)
FROM atable
)
UPDATE newIDs
SET stepId = newStepId
;
The ROW_NUMBER function assigns row numbers in the descending order of stepId, returning them alongside corresponding current values of stepId. Since the newIDs CTE derives rows from a single table, that makes the CTE updatable, so you can use it as the target of UPDATE and simply assign every stepId the newly generated row number.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 months ago.
Improve this question
Let's say I have the table structure as shown below. Which SQL script can I use to update the column Size2 in the table, with the sum of column Size, when the animals are equal? Platform is SQL Server.
I want to have a column Size2 that is the sum of the Size when animal names equal each other. I'm struggling to put the script below into an update statement but please see the select statement.
CREATE TABLE table1
(
Size nvarchar(50),
Animals nvarchar(250),
Part int,
Size2 nvarchar(250)
);
Size
Animals
Part
30
Pig
1
60
Tiger
1
10
Tiger
2
30
Pig
2
90
Lion
1
20
Lion
2
10
Lion
3
This is the desired output, I do not have a Size2 column in the table yet.
Size
Animals
Part
Size2
30
Pig
1
60
60
Tiger
1
70
10
Tiger
2
70
30
Pig
2
60
90
Lion
1
120
20
Lion
2
120
10
Lion
3
120
So far I have:
SELECT
Animals,
SUM(TRY_CONVERT(int, Size))
FROM
Table1
WHERE
Part IS NOT NULL
GROUP BY
Animals
For select statement, you can use PARTITION BY clause
This is select statement
SELECT Size, Animals, Part,
SUM(CAST(size as int)) OVER(PARTITION BY Animals) As total_size
FROM table1
WHERE part IS NOT NULL;
For update statement
UPDATE table1
SET table1.size2 = table2.total_size
FROM
table1
INNER JOIN
(SELECT Size, Animals, Part,
SUM(CAST(size as int)) OVER(PARTITION BY Animals) As total_size
FROM table1
WHERE part IS NOT NULL) AS table2
ON table1.size = table2.size AND
table1.animals = table2.animals AND
table1.part = table2.part;
Note: UPDATE statement above will only update size2 column where part is not null.
If you want to update all size2 column even though part is null, remove last line(table1.part = table2.part) will do
The desired result can be achieved by following SQL
SELECT t.Size, t.Animal, t.Part, t2.AnimalSum
FROM table1 t RIGHT JOIN
(SELECT Animal, Sum(convert(int,Size)) AS AnimalSum
FROM table1
group BY Animal) AS t2 ON t.Animal = t2.Animal
so the update can be easily done with an update using above query statement.
From your query, you can update with this
UPDATE t1
SET
t1.Size2 = t2.SumSize
FROM Table1 t1
INNER JOIN
(SELECT Animals, SUM(TRY_CONVERT(int,Size)) as SumSize
FROM Table1
WHERE Part IS NOT NULL
GROUP BY Animals) t2
ON t1.Animals = t2.Animals
I am attempting to update a table that contains deed information. Specifically property ID, sale sequence, and deed date. The program generates the sale sequence data sequentially regardless of the deed date or prior deed information for the property in question.
[property_ID] [sale_number] [sale_deed_date]
1 1 01/15/1990
1 2 06/25/1970
1 3 08/12/1930
What I would like to accomplish is re-sequence sale_number data so they are in chronological order. Similar to this:
[property_ID] [sale_number] [sale_deed_date]
1 1 08/12/1930
1 2 06/25/1970
1 3 01/15/1990
Any help with this would be greatly appreciated.
You can do this by grabbing the correct order in a cte:
;WITH cte AS (SELECT property_ID, sales_number, sales_deed_date, rn = ROW_NUMBER() OVER (PARTITION BY Property_ID ORDER BY sales_deed_date) FROM tablename)
UPDATE t
SET t.sales_number = cte.rn
FROM tablename t
INNER JOIN cte ON t.property_ID = cte.property_ID AND t.sales_deed_date = cte.sales_deed_date
This is table structure !
name varchar(10),
score float
With values:
('Alex',7),('john',5.6),('Tom',8.9),('Anonio',6),('sharti',7),('mamuzi',9)
I need o/p
name score
mamuzi 9
Tom 8.9
Alex 7
sharti 7
When i try using TOP as : select top 3 * from table order by score desc I can't get the expected results
Try using with Ties in sql server since Alex and sharti have same score
select top 3 with ties * from #t order by score desc
See here
Unless you include an ORDER BY statement, the ordering will be random when you use TOP.
Do this:
SELECT TOP 3 WITH TIES * FROM YourTable ORDER BY score DESC
Sample SQL Fiddle.
From the documentation:
When TOP is used in conjunction with the ORDER BY clause, the result
set is limited to the first N number of ordered rows; otherwise, it
returns the first N number of rows in an undefined order.
Edit: just noticed the change in your sample data. To make it work now you need to add the WITH TIES clause to TOP, as pointed out in the other answers. I've updated my answer accordingly.
You forgot ordering by score field. Modify your query as:
SELECT TOP 3 * FROM table ORDER BY score DESC
Answer for the last edit to your question: Using TOP and ORDER BY DESC worked for me but i tested with the new values you added to your question. My test was as follows:
DECLARE #table TABLE
(
name varchar(10),
score float
)
INSERT INTO #table VALUES ('Alex', 7)
INSERT INTO #table VALUES ('john',5.6)
INSERT INTO #table VALUES ('Tom',8.9)
INSERT INTO #table VALUES ('Anonio',6)
INSERT INTO #table VALUES ('sharti',7)
INSERT INTO #table VALUES ('mamuzi',9)
SELECT TOP 3 * FROM #table ORDER BY score DESC
It works since the result is as expected.
To include sharti and his score in the results since he has the same score as Alex, you will need to use WITH TIES as Vijaykumar Hadalgi suggested (More for WITH TIES).
Modify your query as: SELECT TOP(3) WITH TIES * FROM #table ORDER BY score DESC
name score
--------------
mamuzi 9
Tom 8,9
Alex 7
sharti 7
In M.C.Q test, when user come back to the same question again how can I track the last answer given for the question?,
following is the table structure
Method: 1
temptblUserAnswer
id uid qid ansid
1 1 1 5
2 1 2 6
Should I update the table value for that particular Question? OR Should I use following table structure?
Method: 2
temptblUserAnswer
id uid qid ansid timestamp
1 1 1 5 2011-09-28 11:54:32
2 1 2 12 2011-09-28 11:58:40
3 1 1 7 2011-09-28 12:02:50
Here with the help of timestamp I can find the the last answer for any particular question.
Now the question is, which method to follow, and which will be performance oriented?
Or any better suggestion for the same? Should I go with Method:1 and apply the index on uid, ansid column?
If your Id is autoincrementing, you can get last answer based on Id:
SELECT TOP 1 AnsID
WHERE Uid=#UserId AND Qid=#QuestionID
ORDER BY Id DESC
About performance:you should put non-clustered index on Uid AND Qid AND ID and Include AnsID
You can avoid of using timestamp column in this table.
1: For the first method:
To get the last answer id for a given question id, you can use this script:
--index creation
CREATE UNIQUE INDEX IUN_temptblUserAnswer_qid_id ON temptblUserAnswer(uid,qid,id DESC);
--query
DECLARE #QuestionID INT, #UserID INT;
SELECT #QuestionID=123, #UserID = 456;
SELECT TOP 1 ansid
FROM temptblUserAnswer
WHERE qid = #QuestionID
AND uid = #UserID
ORDER BY id DESC;
In this case, I have assumed that the last answer is given by the last temptblUserAnswer.id. Also I have assumed that temptblUserAnswer.id is IDENTITY(1,1).
Problem: if somebody runs an ad-hoc insert on temptblUserAnswer table it's possible to get wrong results.
2: For the second method:
You should use a date/time data type with higher precision (for SQL version<=SQL2005: DATETIME is the only option, for SQL version>SQL2005 you can use DATETIME2(7) data type and SYSDATETIME() function instead of GETDATE()/CURRENT_TIMESTAMP functions). Even so, you could get two or more answers with the same timestamp. In this case, you could use 'temptblUserAnswer.id' column as the second criteria.
--index creation
CREATE UNIQUE INDEX IUN_temptblUserAnswer_qid_id ON temptblUserAnswer(uid,qid,timestamp DESC, id DESC);
--query
DECLARE #QuestionID INT, #UserID INT;
SELECT #QuestionID=123, #UserID = 456;
SELECT TOP 1 ansid
FROM temptblUserAnswer
WHERE qid = #QuestionID
AND uid = #UserID
ORDER BY timestamp DESC, id DESC;
I have a situation where I need to add an arbitrary unique id to each of a group of records. It's easier to visualize this below.
Edited 11:26 est:
Currently the lineNum field has garbage. This is running on sql server 2000. The sample that follows is what the results should look like but the actual values aren't important, the numbers could anything as long as the two combined fields can be used for a unique key.
OrderID lineNum
AAA 1
AAA 2
AAA 3
BBB 1
CCC 1
CCC 2
The value of line num is not important, but the field is only 4 characters. This needs to by done in a sql server stored procedure. I have no problem doing it programatically.
Assuming your using SQL Server 2005 or better you can use Row_Number()
select orderId,
row_number() over(PARTITION BY orderId ORDER BY orderId) as lineNum
from Order
While adding a record to the table, you could create the "linenum" field dynamically:
In Transact-SQL, something like this:
Declare #lineNum AS INT
-- Get next linenum
SELECT #lineNum = MAX(COALESCE(linenum, 0)) FROM Orders WHERE OrderID = #OrderID
SET #lineNum = #lineNum + 1
INSERT INTO ORDERS (OrderID, linenum, .....)
VALUES (#OrderID, #lineNum, ....)
You could create a cursor that reads all values sorted, then at each change in value resets the 1 then steps through incrementing each time.
E.g.:
AAA reset 1
AAA set 1 + 1 = 2
AAA set 2 + 1 = 3
BBB reset 1
CCC reset 1
CCC set 1 + 1 = 1
Hmmmmm, could you create a view that returns the line number information in order and group it based on your order ID? Making sure the line number is always returned in the same order.
Either that or you could use a trigger and on the insert calculate the max id for the order?
Or perhaps you could use a select from max statement on the insert?
Perhaps none of these are satisfactory?
If you're not using SQL 2005 this is a slightly more set based way to do this (I don't like temp tables much but I like cursors less):
declare #out table (id tinyint identity(1,1), orderid char(4))
insert #out select orderid from THESOURCETABLE
select
o.orderid, o.id - omin.minid + 1 as linenum
from #out o
inner join
(select orderid, min(id) minid from #out group by orderid) as omin on
o.orderid = omin.orderid