Row Offset in SQL Server - sql-server-2005

SELECT name FROM employee
ORDER BY Id
OFFSET 5 ROWS
FETCH NEXT 5 ROWS ONLY;
I write this query but getting error msg. plz help me
Msg 102, Level 15, State 1, Line 6
Incorrect syntax near 'OFFSET'.
Msg 153, Level 15, State 2, Line 7
Invalid usage of the option NEXT in the FETCH statement.

You can do a sub query like:
select top 5 name
from (
select top 10 id, name
from employee
order by id) as x
order by id desc
This will return rows 6 through 10.

Related

SQL query to select equal or less than or greater than

Assuming that there is a table t with the following columns: Code int, Name nvarchar(50).
I'd would like to query the table for the most matching row for a given Code c. The 'most matching' criteria (in order of importance):
1) select a row whose Code matches c
2) select a row whose Code is greater than c (but the very first one). For example, if c = 4 and t
contains 1, 2, 3, 5, 6, and 7, I'd like to select 5.
3) select a row whose
Code is less than c. For example, if c = 4 and t contains 3, 2, and
1, I'd like to select 3.
The code is going to be in a stored procedure.
Could someone please suggest how to accomplish the above.
Thanks.
Sample data and expected results:
1, "Name1"
2, "Name2"
4, "Name4"
5, "Name5"
If c=2, result: 2,"Name2"
If c=3, result: 4,"Name4"
if c=6, result: 5,"Name5"
I'd order the rows by two criteria - the absolute distance from the target number and whether it's greater or lesser than it, and just pick the top row. E.g., assuming the target code is 4:
SELECT TOP 1 *
FROM t
ORDER BY ABS(code - 4) ASC, CASE WHEN code > 4 THEN 1 ELSE 0 END DESC
That is a top 1 query; you want the one best matching record. So select TOP 1 along the desired order in ORDER BY.
select top 1 *
from mytable
order by
case when code = #code then 1
when code > #code then 2
else 3
end,
abs(code - #code);

How to select row values for max(2 columns)

I am working out a query in MS SQL Server. I have my table like this
Table( Level int, Stage int, values varchar)
Level Stage Value
1 1
1 2
1 3
2 1
2 2
I need to find the row having maximum value by level and then by stage. ie., I need to get the result as
Level Stage
2 2
When I try the below query I get the value 22 and in one column. I need that in 2 distinct columns as specified above.
SELECT MAX(CAST(wfLevel as varchar(2)) + CAST(approvalStage as varchar(2)))
FROM [AuditReporterDB].[dbo].[RequestHistory]
Can anyone help.
SELECT TOP 1 Level,Stage
FROM tableName
ORDER BY Level Desc,Stage Desc

How can I use OVER and ORDER BY

I can't understand this code's bug.
CODE:
SELECT
CariID, HesapID, BTrh, BCinsiID, BNo, Acklm, VdTrh, mTrh, BorcT, AlacakT,
SUM(BorcT) OVER (PARTITION BY CariID, HesapID ORDER BY BTrh, BNo, mTrh) AS TopBorcT,
SUM(AlacakT) OVER (PARTITION BY CariID, HesapID ORDER BY BTrh, BNo, mTrh ) AS TopAlacakT
FROM
tCariH
ERROR:
Msg 102, Level 15, State 1, Line 3
Incorrect syntax near 'order'.
With an aggregate function like SUM, you don't use ORDER BY in the OVER clause - you only need to use the PARTITION function. The ORDER is used for ranking functions:
Depending on the ranking, aggregate, or analytic function used with the OVER clause, <ORDER BY clause> and/or the <ROWS and RANGE clause> may not be supported.
Just modify to remove the ORDER in both your aggregates and you should be fine.
Apparently this is not supported in SQL Server 2008, but it is support in SQL Server 2012
How to use partition by and order by in over function?
Try this tool and you can see why:
http://sqlfiddle.com/#!6/5303f/1
ID AccountID Quantity
1 1 10 Sum = 10
2 1 5 = 10 + 5 = 15
3 1 2 = 10 + 5 + 2 = 17
4 2 7 = 7
5 2 3 = 7 + 3 = 10
SELECT ID, AccountID, Quantity,
SUM(Quantity) OVER (PARTITION BY AccountID ) AS TopBorcT,
FROM tCariH

How to multiply values from different rows and different columns?

This what the table looks like.
Code Items Unit QTY Price Total
------- --------- ---- ---- ----- -----
HTM001 Cable Tie pcs null 1.00 ?
HTM001s Cable Tie null 20 null
and I tried a query like this...
SELECT VRIJ1 FROM dbo.INVELE WHERE FK_BODEFINITOIN_USERDEFINED IN (894) AS QTY,
SELECT RESTWRDE FROM dbo.INVELE WHERE FK_BODEFINITOIN_USERDEFINED IN (898) AS PRICE,
(QTY*PRICE) AS TOTAL
FROM dbo.INVELE
then I got these:
Msg 156, Level 15, State 1, Line 4
Incorrect syntax near the keyword 'AS'.
Msg 156, Level 15, State 1, Line 5
Incorrect syntax near the keyword 'AS'.
what I want is to like this 20*1.00=Total.
Anyone Please help!!!
;WITH T1(QTY, CODE) AS
(
SELECT VRIJ1, LEFT(CODE, 7)
FROM dbo.INVELE
WHERE FK_BODEFINITION_USERDEFINED IN (894)
),
T2(PRICE, CODE) AS
(
SELECT RESTWRDE, CODE
FROM dbo.INVELE
WHERE FK_BODEFINITION_USERDEFINED IN (898)
)
SELECT T1.QTY,
T2.PRICE,
T1.QTY*T2.PRICE AS TOTAL
FROM T1
INNER JOIN T2
ON T1.CODE = T2.CODE

Special order by on SQL query

I need to display a list of records from a database table ordered by some numeric column. The table looks like this:
CREATE TABLE items (
position int NOT NULL,
name varchar(100) NOT NULL,
);
INSERT INTO items (position, name) VALUE
(1, 'first'),
(5, 'second'),
(8, 'third'),
(9, 'fourth'),
(15, 'fifth'),
(20, 'sixth');
Now, the order of the list should change according to a parameter provided by the user. This parameter specifies which record comes first like this:
position = 0
order should be = 1, 5, 8, 9, 15, 20
position = 1
order should be = 20, 1, 5, 8, 9, 15
position = 2
order should be = 15, 20, 1, 5, 8, 9
In other words the last record becomes the first and so on. Can you think of a way to do this in SQL?
I'm using MySQL but an example in any SQL database will do.
Thanks
See how this works for you. Uses generic SQL so it should be valid for MySql (untested) as well.
DECLARE #user_sort INTEGER
SET #user_sort = 0
SELECT position, name FROM
(
SELECT I1.position, I1.name, COUNT(*) AS rownumber, (SELECT COUNT(*) FROM items) AS maxrows
FROM items I1, items I2
WHERE I2.position <= I1.position
GROUP BY I1.position, I1.name
) Q1
ORDER BY
CASE WHEN maxrows - rownumber < (#user_sort % maxrows) THEN 1 ELSE 2 END, position
Note:
* If the user provided sort index is greater than the row count, the value will wrap to within the valid range. To remove this functionality, remove the "% maxrows" from the ORDER BY.
Results:
SET #user_sort = 0
position name
1 first
5 second
8 third
9 fourth
15 fifth
20 sixth
SET #user_sort = 1
position name
20 sixth
1 first
5 second
8 third
9 fourth
15 fifth
SET #user_sort = 2
position name
15 fifth
20 sixth
1 first
5 second
8 third
9 fourth
SET #user_sort = 9
9 fourth
15 fifth
20 sixth
1 first
5 second
8 third
Are you sure you want to do this in SQL?
To me, this sounds like you should load the results in a dataset of some sort, and then either re-order them as you want, or position the starting point at the correct position.
Possibly using a linked list.
ORDER BY (FIELD(position, 1, 5, 8, 9, 15, 20) + parameter) % 7
Edit: To make the peanut gallery happy, the general solution is:
ORDER BY (SELECT ix + parameter - 1 FROM (SELECT i.position, #ix := #ix + 1 AS ix FROM (SELECT #ix := 0) AS n, items AS i ORDER BY position) AS s WHERE s.position = items.position) % (SELECT COUNT(*) FROM items)
I'm riffing on beach's solution here, but eliminating the self-join and only selecting from the items table twice (and using Oracle syntax):
select
i.position
, i.name
from(
select
items.*
, ( SELECT COUNT(*) FROM items ) AS maxrows
from items
order by position
) i
order by
case
when rownum > maxrows - 2 -- NOTE: change "2" to your "position" variable
then 1 - 1 / rownum -- pseudo-rownum < 1, still ascending
else
rownum
end
;
If it's a set list that you know the number of items you could do something like:
SELECT *
FROM Items
ORDER BY CASE WHEN Position >= Position THEN POSITION ELSE Position+1000 END
But its really ugly.
This really is not an ideal thing to be doing in SQL.
I have solution, but with large tables it will be slow.
DECLARE #iOrder INT
SET #iOrder = 4
SELECT abc.position,abc.name FROM
(
SELECT position,name,ROW_NUMBER() OVER (ORDER BY position) AS rownum
FROM items
) abc
WHERE abc.rownum >= #iOrder
UNION ALL
SELECT def.position, def.name FROM
(
SELECT position,name,ROW_NUMBER() OVER (ORDER BY position) AS rownum
FROM items
) def
WHERE def.rownum < #iOrder
Note that the use of UNION (Without the all) will reorder the results as it'll be looking for duplicates
As per John's comment, but with LIMIT syntax instead (ROW_NUMBER/OVER doesn't work in MySQL and besides LIMIT is much easier to read):
(
SELECT position, name FROM items
ORDER BY position
LIMIT #offset, #bignum
) UNION ALL (
SELECT position, name FROM items
ORDER BY position
LIMIT #offset
)
Where #bignum is an arbitrary number higher than any number of results you might have.
I'm still not wholly convinced this will in practice be faster than rearranging the list on the web server... would depend exactly how you were dealing with the result set and how big it was, I suppose. But at least it avoids the self-cross-join involved in beach's clever approach.