SQL Server processing for jquery datatables order by issue? - sql

I have written the following script to mimic the incoming parameters from datatables and try to filter the results using the parameters. Everything works fine except the order by clause. Basically it only orders by rownumber and does not take into consideration the case statement which provides the second order by column.
declare #sSortColumn as nvarchar(50)='Country';
declare #sSortDirection as nvarchar(5) = 'Desc';
declare #sSearch as nvarchar(50) = '';
declare #iDisplayLength as int = 20;
declare #iDisplayStart as int = 20;
declare #sIDsearch as int = CASE WHEN ISNUMERIC(#sSearch) = 1 THEN CAST(#sSearch AS INT) ELSE 0 END;
WITH media AS
(
select ROW_NUMBER() OVER (ORDER BY mc.id) as RowNumber,
mc.id,mc.Name, mc.CityID,lc.Name as Country
from Lookup_MediaChannels mc
left join Lookup_SonarMediaTypes st on mc.SonarMediaTypeID = st.ID
left join Lookup_SonarMediaGroups sg on sg.ID = st.SonarMediaGroupID
left join Lookup_MediaTypes mt on mc.MediaTypeID = mt.ID
left join Lookup_SonarMediaGroups sg1 on sg1.ID = mt.MediaGroupID
left join lookup_Countries lc on lc.id = mc.countryid
where mc.Name like '%'+#sSearch+'%'
and (sg1.ID=1 or sg.ID =1 )
or mc.id = #sIDsearch
)
SELECT RowNumber, Name, Country
FROM media
WHERE RowNumber BETWEEN (#iDisplayStart+ 1) AND (#iDisplayStart+ #iDisplayLength)
order by rownumber,
CASE WHEN #sSortColumn = 'Name' AND #sSortDirection = 'Desc'
THEN Name END DESC,
CASE WHEN #sSortColumn = 'Name' AND #sSortDirection != 'Desc'
THEN Name END,
CASE WHEN #sSortColumn = 'Country' AND #sSortDirection = 'Desc'
THEN Country END DESC,
CASE WHEN #sSortColumn = 'Country' AND #sSortDirection != 'Desc'
THEN Country END

This simplified example may help you
http://sqlfiddle.com/#!6/35ffb/10
Set up some dummy data (this would be replaced by your select statement)
create table x(
id int,
name varchar(3),
country varchar(2)
)
insert into x
values (1,'aaa','uk'),
(2,'aaa','us'),
(3,'baa','uk'),
(4,'caa','uk'),
(5,'baa','it')
Some vars to hold sort field and sort order
declare #so char(1)
declare #sf char(1)
set #so = 'a' -- a = asc d = desc
set #sf = 'n' -- n = name c = country
and a select to return sorted data
SELECT row_number()
OVER (order by
CASE WHEN #so = 'd' THEN sf END desc,
CASE WHEN #so <> 'd' THEN sf end,
id
) AS aa, name,country
FROM (
SELECT x.*, case #sf when 'n' then name when 'c' then country end sf
FROM X
) X

Related

Unable to Update the Records in the Table

I am trying to update values from one table to another. SQL Server is showing 1 row(s) affected. But records do not get updated.
This is the Merge update I am using:
MERGE dbo.Patients p
USING #Patient_Already_in_System s
ON p.PatientID = s.PatientID
WHEN MATCHED AND s.Student_ID = 165364
THEN UPDATE
SET FirstName = CAST(SUBSTRING(s.Client_First_Name,1,25) AS VARCHAR(25))
,LastName = CAST(SUBSTRING(s.Client_Last_Name,1,35) AS VARCHAR(35))
,MiddleName = CAST(s.Student_ID AS VARCHAR(25))
,Street = CAST(s.Address AS VARCHAR(100))
,StateID = CAST(s.State AS CHAR(2))
,ZipCode = CAST(s.Zip AS varchar(10))
,Gender = ( SELECT id FROM dbo.lkpGenderIdentityExym WHERE id = s.gender)
,DOB = CAST(s.DOB AS DATETIME)
,Hispanic = CASE WHEN s.Ethnicity2 = 'No, not Hispanic or Latino' THEN CAST(0 AS BIT)
WHEN s.Ethnicity2 = 'Yes, Hispanic or Latino' THEN CAST(1 AS BIT)
ELSE NULL
END
,GradeLevel = CAST(s.grade AS VARCHAR(25))
,RaceID = (SELECT ID FROM dbo.lkpRace WHERE DMHDescriptionForCSIRace = s.race)
,Location = (SELECT id FROM dbo.Locations WHERE Description LIKE s.Location OR Description LIKE s.Location + ' High')
,AssignedToID = CASE WHEN (SELECT id FROM dbo.lkpUsers WHERE FullName = s.Primary_Therapist) IS NULL THEN 809 -- Z-EXYM-Malik Qayyum
ELSE (SELECT id FROM dbo.lkpUsers WHERE FullName = s.Primary_Therapist)
END;
I have also tried a regular UPDATE Table Set ..... Same thing. Any pointers on what I am missing?

sql server - How can I put the values in a result side by side

CREATE TABLE #E (
ID INT ,
NAME VARCHAR(20),
RESULT VARCHAR(20)
)
INSERT INTO #E VALUES (1,'DOMAIN','marka')
INSERT INTO #E VALUES (1,'EXTENSION','.com')
INSERT INTO #E VALUES (1,'TYPE','WEB')
SELECT * FROM #E
Declare #DomainName varchar(20) = ''
--How can I put the values(RESULT) in a result side by side
SELECT RESULT FROM #E WHERE ID=1 AND NAME IN ('DOMAIN','EXTENSION')
How can I put the values(RESULT) in a result side by side
How can I do it? --> Set #DomainName = 'marka.com'
#DomainName = 'marka.com' --How do I add
Are you looking for conditional aggregation?
select max(case when name = 'DOMAIN' then result end) as domain,
max(case when name = 'EXTENSION' then result end) as extension,
max(case when name = 'TYPE' then result end) as type
from #E e
group by id;
WITH res1
AS (
SELECT result
,ID
FROM #E
WHERE name = 'DOMAIN'
)
,res2
AS (
SELECT result
,ID
FROM #E
WHERE name = 'EXTENSION'
)
SELECT CONCAT (
res1.result
,res2.result
)
FROM RES1
INNER JOIN RES2 ON RES1.ID = RES2.ID
Demo
DECLARE #DomainName varchar(20) = ''
SELECT #DomainName = (DOMAIN + EXTENSION) FROM
(
SELECT *
FROM #E
WHERE ID=1
AND NAME IN ('DOMAIN','EXTENSION')
) as main
PIVOT
(
MAX(RESULT)
FOR NAME IN ([DOMAIN],[EXTENSION])
) piv
SELECT #DomainName

ORDER BY clause is not sorting by alias in SQL Server

I have a query like this:
DECLARE #Sortorder VARCHAR(5) = 'asc',
#ColumnNumber INT = 9
SELECT
SUBSTRING(csu.UserName, CHARINDEX(CHAR(92), csu.UserName) + 1, LEN(csu.UserName)) AS UserName, w.WorkItemId
FROM [tasks].[WorkItems] w
LEFT JOIN operations.CustomerServiceUser csu ON csu.UserId = w.AssignedToUserId
WHERE
w.[ShowInTaskList] = 1 AND UserName IS NOT NULL
ORDER BY
CASE WHEN #ColumnNumber = 9 AND #SortOrder = 'asc' THEN UserName END ASC,
CASE WHEN #ColumnNumber = 9 AND #SortOrder = 'desc' THEN UserName END DESC
When I do that the data is not sorted by UserName in any order asc or desc, but when I do this:
SELECT
SUBSTRING(csu.UserName, CHARINDEX(CHAR(92), csu.UserName) + 1, LEN(csu.UserName)) AS UserName, w.WorkItemId
FROM [tasks].[WorkItems] w
LEFT JOIN operations.CustomerServiceUser csu ON csu.UserId = w.AssignedToUserId
WHERE
w.[ShowInTaskList] = 1 AND UserName IS NOT NULL
ORDER BY
UserName
What am I doing wrong in the dynamic order by? The values are the same in the declared variables and in the case. To be frank I don't know what keywords I should pass to google ;) Many thanks for the answer.
You have the column UserName and an alias UserName. It is the column value that is being used to sort the results, not the alias. While it is perfectly acceptable to use an alias name inside the ORDER BY clause, it cannot be used inside CASE WHEN statement.
The solution is to use a sub-query (or CTE):
DECLARE
#Sortorder VARCHAR(5) = 'asc',
#ColumnNumber INT = 9
SELECT * FROM (
SELECT SUBSTRING(csu.UserName, /* removed for readability */) AS UserNameCopy, w.WorkItemId
FROM [tasks].[WorkItems] w
LEFT JOIN operations.CustomerServiceUser csu ON csu.UserId = w.AssignedToUserId
WHERE w.[ShowInTaskList] = 1 AND UserName IS NOT NULL
) AS SubQuery
ORDER BY
CASE WHEN #ColumnNumber = 9 AND #SortOrder = 'asc' THEN SubQuery.UserNameCopy END ASC,
CASE WHEN #ColumnNumber = 9 AND #SortOrder = 'desc' THEN SubQuery.UserNameCopy END DESC
You can use CROSS APPLY to make your code look more friendly. It does not affect performance:
DECLARE
#Sortorder VARCHAR(5) = 'asc' ,
#ColumnNumber INT = 9;
SELECT
SUBSTRING(csu.UserName, CHARINDEX(CHAR(92), csu.UserName) + 1,
u.UserName ,
w.WorkItemId
FROM
[tasks].[WorkItems] w
LEFT JOIN operations.CustomerServiceUser csu ON csu.UserId = w.AssignedToUserId
CROSS APPLY (SELECT LEN(csu.UserName) AS UserName ) u
WHERE
w.[ShowInTaskList] = 1
AND UserName IS NOT NULL
ORDER BY
CASE WHEN #ColumnNumber = 9
AND #Sortorder = 'asc' THEN u.UserName
END ASC ,
CASE WHEN #ColumnNumber = 9
AND #Sortorder = 'desc' THEN u.UserName
END DESC;
And example with the data:
CREATE TABLE #a ( aColumn INT, b INT );
INSERT INTO #a
VALUES
( 1, 1 ),
( 1, 2 ),
( 2, 1 ),
( 3, 1 ),
( 1, 3 ),
( 4, 4 );
DECLARE
#Sortorder VARCHAR(5) = 'asc' ,
#ColumnNumber INT = 9;
SELECT
aColumn ,
b aColumn
FROM
#a tbl
CROSS APPLY (
SELECT
CAST(( tbl.aColumn + 1 - 2 ) * 5 AS VARCHAR(100)) r /*or any other kind of operation, such as substring etc*/
) shortcut
ORDER BY
CASE WHEN #ColumnNumber = 9
AND #Sortorder = 'asc' THEN shortcut.r
END ASC ,
CASE WHEN #ColumnNumber = 9
AND #Sortorder = 'desc' THEN shortcut.r
END DESC;
DROP TABLE #a;
I think you can achieve this easily with Dynamic SQL (it worked for me):
DECLARE #statement NVARCHAR(MAX) ,
#SortOrder VARCHAR(5) = 'desc' ,
#columnNumber INT = 9
SET #statement = N'
SELECT
SUBSTRING(csu.UserName, CHARINDEX('\ ',csu.UserName) + 1, LEN(csu.UserName)) as UserName, w.WorkItemId
FROM [tasks].[WorkItems] w
LEFT JOIN operations.CustomerServiceUser csu
ON csu.UserId = w.AssignedToUserId
WHERE
w.[ShowInTaskList] = 1
AND UserName is not null
ORDER BY' +
CASE
WHEN (#ColumnNumber = 9 AND #SortOrder = 'asc') THEN 'UserName ASC'
WHEN (#columnNumber = 9 AND #SortOrder = 'desc') THEN 'UserName DESC'
ELSE 'CustomerId' END
EXEC sys.sp_executesql #statement
GO
I believe the easy and safe way is to use a CTE:
;WITH CTE AS
(
SELECT ROW_NUMBER() OVER (ORDER BY UserName ASC) As AscOrder,
ROW_NUMBER() OVER (ORDER BY UserName DESC) As DescOrder,
-- editor note: CHARINDEX is for '\' and not '\ ', but it messes up the code coloring system of SO, so I've added a space.
SUBSTRING(csu.UserName, CHARINDEX('\ ',csu.UserName) + 1,LEN(csu.UserName)) as UserName, w.WorkItemId
FROM [tasks].[WorkItems] w
LEFT JOIN operations.CustomerServiceUser csu ON csu.UserId = w.AssignedToUserId
WHERE w.[ShowInTaskList] = 1
AND UserName is not null
)
SELECT *
FROM CTE
ORDER BY CASE WHEN #ColumnNumber = 9 AND #SortOrder = 'asc' THEN AscOrder
WHEN #ColumnNumber = 9 AND #SortOrder = 'desc' THEN DescOrder
END

Paging of records using sql server stored procedure

I have a stored procedure which returns result from two tables using outer join and where conditions. It has order by clause as well. I want to add paging to it so that only requested number of records are returned. How can I do it? I need to supply pagenumber, totalnumber of records, current page etc ? My stored procedure is:
CREATE PROCEDURE [dbo].[hr_SearchVacanciesForService]
#SearchText NVARCHAR(50) = NULL,
#DutyStationID INT = NULL,
#VacancyCategoryIDs VARCHAR(1000) = NULL,
#Language INT = 1
AS
SELECT *
FROM dbo.hr_Vacancies LEFT OUTER JOIN dbo.hr_DutyStations ON dbo.hr_Vacancies.DutyStationID = dbo.hr_DutyStations.DutyStationID
LEFT OUTER JOIN dbo.hr_Companies
ON dbo.hr_Vacancies.CompanyID = dbo.hr_Companies.CompanyID
WHERE dbo.hr_Vacancies.Deleted = 0
AND (dbo.hr_Vacancies.JobTitleLang1 LIKE #LoacalSeacrchText
OR dbo.hr_Vacancies.JobTitleLang2 LIKE #LoacalSeacrchText
OR dbo.hr_Vacancies.DescriptionLang1 LIKE #LoacalSeacrchText
OR dbo.hr_Vacancies.DescriptionLang2 LIKE #LoacalSeacrchText
AND (dbo.hr_Vacancies.DutyStationID = #DutyStationID OR #DutyStationID IS NULL OR #DutyStationID = 0)
ORDER BY HavePriority DESC, StartDate DESC, dbo.hr_Vacancies.VacancyID DESC
Use option with CTE and OVER() clause
CREATE PROCEDURE [dbo].[hr_SearchVacanciesForService]
#SearchText NVARCHAR(50) = NULL,
#DutyStationID INT = NULL,
#VacancyCategoryIDs VARCHAR(1000) = NULL,
#Language INT = 1,
#NumberOfPages int
AS
;WITH cte AS
(
SELECT *, ROW_NUMBER() OVER (ORDER BY HavePriority DESC, StartDate DESC, dbo.hr_Vacancies.VacancyID DESC) AS Pages
FROM dbo.hr_Vacancies LEFT OUTER JOIN dbo.hr_DutyStations ON dbo.hr_Vacancies.DutyStationID = dbo.hr_DutyStations.DutyStationID
LEFT OUTER JOIN dbo.hr_Companies ON dbo.hr_Vacancies.CompanyID = dbo.hr_Companies.CompanyID
WHERE dbo.hr_Vacancies.Deleted = 0
AND (dbo.hr_Vacancies.JobTitleLang1 LIKE #LoacalSeacrchText
OR dbo.hr_Vacancies.JobTitleLang2 LIKE #LoacalSeacrchText
OR dbo.hr_Vacancies.DescriptionLang1 LIKE #LoacalSeacrchText
OR dbo.hr_Vacancies.DescriptionLang2 LIKE #LoacalSeacrchText
AND (dbo.hr_Vacancies.DutyStationID = #DutyStationID OR #DutyStationID IS NULL OR #DutyStationID = 0)
)
SELECT *, COUNT(*) OVER() AS totalOfPages
FROM cte
WHERE Pages BETWEEN 1 AND ISNULL(#NumberOfPages, Pages)
Example using OVER() clause with expressions:
SELECT ... ROW_NUMBER() OVER (ORDER BY
CASE WHEN dbo.hr_Vacancies.Priority = 0
THEN 0 ELSE
CASE WHEN CONVERT(DATETIME,CONVERT(CHAR(10),dbo.hr_Vacancies.PriorityDateExpired,101)) > CONVERT(DATETIME,CONVERT(CHAR(10),GETDATE(),101)) OR dbo.hr_Vacancies.PriorityDateExpired IS NULL
THEN 1 ELSE 0 END END DESC, your_second_expression_StartDate DESC)
If you want to show records from 20 to 30:
CREATE PROCEDURE [dbo].[hr_SearchVacanciesForService]
#SearchText NVARCHAR(50) = NULL,
#DutyStationID INT = NULL,
#VacancyCategoryIDs VARCHAR(1000) = NULL,
#Language INT = 1,
#StartPage int = NULL,
#EndPage int = NULL
AS
;WITH cte AS
(
SELECT *, ROW_NUMBER() OVER (ORDER BY your_case_expressionForColumnHavePriority DESC, your_case_expressionForColumnStartDate DESC, dbo.hr_Vacancies.VacancyID DESC) AS Pages
FROM dbo.hr_Vacancies LEFT OUTER JOIN dbo.hr_DutyStations ON dbo.hr_Vacancies.DutyStationID = dbo.hr_DutyStations.DutyStationID
LEFT OUTER JOIN dbo.hr_Companies ON dbo.hr_Vacancies.CompanyID = dbo.hr_Companies.CompanyID
WHERE dbo.hr_Vacancies.Deleted = 0
AND (dbo.hr_Vacancies.JobTitleLang1 LIKE #LoacalSeacrchText
OR dbo.hr_Vacancies.JobTitleLang2 LIKE #LoacalSeacrchText
OR dbo.hr_Vacancies.DescriptionLang1 LIKE #LoacalSeacrchText
OR dbo.hr_Vacancies.DescriptionLang2 LIKE #LoacalSeacrchText
AND (dbo.hr_Vacancies.DutyStationID = #DutyStationID OR #DutyStationID IS NULL OR #DutyStationID = 0)
)
SELECT *, COUNT(*) OVER() AS totalOfPages
FROM cte
WHERE Pages BETWEEN ISNULL(#StartPage, Pages) AND ISNULL(#EndPage, Pages)
You can read the following papers :
SQL Server stored procedures to page large tables or queries
Or
Stored Procedure having Sorting, Paging and Filtering
OLD METHOD - Simple Pagination script with (limit,order direction,order column,start index)
#orderColumn int ,
#orderDir varchar(20),
#start int ,
#limit int,
#searchKey varchar(20)
declare #to as int = #start+#limit
select IDENTITY(int, 1, 1) AS SnoID,null as abc, make.link,make.manf,make.name
into #tempMake
from make where status=1 and UPPER(make.name) like upper('%'+#searchKey+'%')
select * from #tempMake where SnoID>#start and SnoID<=#to
order by
CASE WHEN #orderColumn = 1 AND #orderdir = 'desc' THEN #tempMake.[manf] END DESC,
CASE WHEN #orderColumn = 1 AND #orderdir = 'asc' THEN #tempMake.[manf] END ASC,
CASE WHEN #orderColumn = 2 AND #orderdir = 'desc' THEN #tempMake.[link] END DESC,
CASE WHEN #orderColumn = 2 AND #orderdir = 'asc' THEN #tempMake.[link] END ASC
select count(#tempMake.SnoID) as row_count from #tempMake
drop table #tempMake

SQL Server 2000 : generating and incrementing data from column conditionally without using CURSOR

:)
Is there any way to create an index, and incrementing with a given condition, but without CURSOR handling/usage
For example:
The condition in my case is that: "if the current color (this is the item to be checked) is the same as the last one: not increment, otherwise increment in one unit"
This must be in a SQL query with no CURSOR USAGE and of course a good time (work with ... 10000 rows at least)
Thanks in advance.
EDIT: I forgot to mention that NEW_INDEX Column doesn't exist. It must be generated with the with the query.
EDIT2: Is there a way that only make use of SELECT/INSERT/UPDATE statements? (not set, declare...)
Assume a table called Colors with fields ID, Color, and ColorIndex of types int, varchar, and int respectively. I also assume the OP means prev / after based on an ordering of the ID field in asc order.
You could do this without a cursor, and use a while loop...but it definately isn't set based:
DECLARE #MyID int
DECLARE #CurrentIndex int
DECLARE #CurrentColor varchar(50)
DECLARE #PreviousColor varchar(50)
SET #CurrentIndex = (SELECT 0)
SET #MyID = (SELECT TOP 1 ID FROM Colors ORDER BY ID ASC)
SET #CurrentColor = (SELECT '')
SET #PreviousColor = (SELECT Color FROM Colors WHERE ID = #MyID)
WHILE (#MyID IS NOT NULL)
BEGIN
IF (#CurrentColor <> #PreviousColor)
BEGIN
SET #PreviousColor = (SELECT Color FROM Colors WHERE ID = #MyID)
SET #CurrentIndex = (SELECT #CurrentIndex + 1)
UPDATE Colors SET ColorIndex = #CurrentIndex WHERE ID = #MyID
END
ELSE
BEGIN
UPDATE Colors SET ColorIndex = #CurrentIndex WHERE ID = #MyID
SET #PreviousColor = (SELECT Color FROM Colors WHERE ID = #MyID)
END
SET #MyID = (SELECT TOP 1 ID FROM Colors WHERE ID > #MyID ORDER BY ID ASC)
SET #CurrentColor = (SELECT Color FROM Colors WHERE ID = #MyID)
END
The result after execution:
Performance wasn't too shabby as long as ID and color are indexed. The plus side is it is a bit faster then using a regular old CURSOR and it's not as evil. Solution supports SQL 2000, 2005, and 2008 (being that you are using SQL 2000 which did not support CTEs).
declare #ID int,
#MaxID int,
#NewIndex int,
#PrevCol varchar(50)
select #ID = min(ID),
#MaxID = max(ID),
#PrevCol = '',
#NewIndex = 0
from YourTable
while #ID <= #MaxID
begin
select #NewIndex = case when Colour = #PrevCol
then #NewIndex
else #NewIndex + 1
end,
#PrevCol = Colour
from YourTable
where ID = #ID
update YourTable
set NewIndex = #NewIndex
where ID = #ID
set #ID = #ID + 1
end
https://data.stackexchange.com/stackoverflow/q/122958/
select
IDENTITY(int,1,1) as COUNTER
,c1.ID
into
#temp
from
CUSTOMERS c1
left outer join (
select
c1.ID, max(p.ID) as PRV_ID
from
CUSTOMERS c1,
(
select
ID
from
CUSTOMERS
) p
where
c1.ID > p.ID
group by
c1.ID
) k on k.ID = c1.ID
left outer join CUSTOMERS p on p.ID = k.PRV_ID
where
((c1.FAVOURITE_COLOUR < p.FAVOURITE_COLOUR)
or
(c1.FAVOURITE_COLOUR > p.FAVOURITE_COLOUR)
or
p.FAVOURITE_COLOUR is null)
update
CUSTOMERS
set
NEW_INDEX = i.COUNTER
--select *
from
CUSTOMERS
inner join (
select
c1.ID, max(t.COUNTER) as COUNTER
from
CUSTOMERS c1,
(
select
ID
,COUNTER
from
#temp
) t
where
c1.ID >= t.ID
group by
c1.ID
) i on i.ID = CUSTOMERS.ID
drop table #temp
select * from CUSTOMERS