Efficient sql server paging - sql-server-2008

Due to the first two comments I've removed all my own code and placed the example directly from 4 guys here.
I'm interested in how the 'select #first_id' should be coded. The example shows the rows being pulled using joins and I would expect that the first_id wouldn't be a valid place to start because it doesn't use the same join syntax.
CREATE PROCEDURE [dbo].[usp_PageResults_NAI]
(
#startRowIndex int,
#maximumRows int
)
AS
DECLARE #first_id int, #startRow int
-- A check can be added to make sure #startRowIndex isn't > count(1)
-- from employees before doing any actual work unless it is guaranteed
-- the caller won't do that
-- Get the first employeeID for our page of records
SET ROWCOUNT #startRowIndex
SELECT #first_id = employeeID FROM employees ORDER BY employeeid
-- Now, set the row count to MaximumRows and get
-- all records >= #first_id
SET ROWCOUNT #maximumRows
SELECT e.*, d.name as DepartmentName
FROM employees e
INNER JOIN Departments D ON
e.DepartmentID = d.DepartmentID
WHERE employeeid >= #first_id
ORDER BY e.EmployeeID
SET ROWCOUNT 0
GO

You can to efficient paging using ROW_NUMBER()
DECLARE #skipRows Int = 10 --Change to input parameter to sp
DECLARE #takeRows Int = 20 --Change to input parameter to sp
SELECT *
FROM (
SELECT
ROW_NUMBER() OVER (ORDER BY a.DateCreated) As RowNumber,
a.PKID,
a.AlertUrl,
a.AlertDescription,
a.Users_PKID_creator,
dbo.Users_GetFullName(a.Users_PKID_creator) as Users_FullName,
a.Dealers_PKID,
d.Dealer,
dbo.convertDateFromUTC(a.DateCreated, #dealers_pkid) as DateCreated,
dbo.convertDateFromUTC(a.DateCreated, #dealers_pkid) as ComparisonDate,
dbo.convertDateFromUTC(a.DateModified, #dealers_pkid) as DateModified,
a.Active,
a.Contacts_PKID,
dbo.Contacts_GetFullName(a.Contacts_PKID) as Contacts_FullName
from Alerts a
join Dealers d on d.PKID = a.Dealers_PKID
where a.DateCreated between dbo.convertDateToUTC(#datetimeDateStart, #dealers_pkid) and dbo.convertDateToUTC(#datetimeDateEnd, #dealers_pkid)
and a.Active = #bitActive
and a.PKID >= #first_id
) AS [t1]
WHERE [t1].RowNumber BETWEEN #skipRows + 1 AND #skipRows + #takeRows

Related

Order a report builder report by the parameters entered

So I have an SSRS report with one parameter and got a request to order the report by the exact order that the parameter/order numbers entered. Is there any way to sort the report this way?
For example, the parameters/order numbers entered in order: 5, 10, 1, 3, 2
I need the report to come out in that exact order
Table:
Order Number
Customer
5
A
10
B
1
C
3
D
2
E
Below is the query too, but I don't think this is anything I could do in sql server anyway.
SELECT c.customer_name AS [Customer]
, oh.order_no AS [Pick Ticket Number]
FROM orders oh
INNER JOIN customer c ON oh.customer_id = c.customer_id
WHERE oh.order_no IN (#orderno)
GROUP BY c.customer_name, oh.order_no
If you are using a drop down list of order numbers for the user to choose from, then I don't you can do this easily as there is no way to know which order they were clicked in.
If the users are just typing into a multivalue parameter and pressing enter between each entry then you can do it like this...
Add new new parameter to your report (this can be hidden) call it something like 'pOrderSort` and set the Default Value expression to be
=JOIN(Parameters!orderno.Value, ",")
This will create a string, something like "5,10,1,3,2".
Now change your dataset query to this..
declare #Seq table(orderNum int, SortBy int IDENTITY(1,1))
INSERT INTO #Seq (orderNum)
SELECT value from string_split(#pOrderSort, ',')
SELECT c.customer_name AS [Customer]
, oh.order_no AS [Pick Ticket Number]
, s.SortBy
FROM orders oh
INNER JOIN customer c ON oh.customer_id = c.customer_id
INNER JOIN #Seq s ON oh.order_no = s.orderNum
GROUP BY c.customer_name, oh.order_no
ORDER BY s.SortBy
All we are doing here is splitting the passed in parameter into rows and assigning a sequence number in the SortBy column.
Now all we do is join to this table and order by the SortBy column. There is no need for the WHERE clause as we are joining only to the order number we need.
You can use the SortBy column in the report design to order the rows as required.
I had to do it without string_split() so below is the code to get around that, other than that I followed Alan's answer with creating a hidden parameter named #orderlist that is joined with the #orderno parameter
DECLARE #str varchar(max)
SET #str = #orderlist
DECLARE #separator varchar(max)
SET #separator = ','
DECLARE #Splited TABLE(id int IDENTITY(1,1), item decimal(19,0))
SET #str = REPLACE(#str, #separator, '''),(''')
SET #str = 'SELECT * FROM (VALUES(''' + #str + ''')) AS V(A)'
INSERT INTO #Splited
EXEC(#str)
SELECT c.customer_name AS [Customer]
, oh.order_no AS [Pick Ticket Number]
FROM oe_hdr oh
INNER JOIN customer c ON oh.customer_id = c.customer_id
INNER JOIN #Splited ot ON ot.item = oh.order_no
GROUP BY c.customer_name, op.pick_ticket_no, ot.id
ORDER BY ot.id ASC

SQL query to select a value based on certain criteria

I have the following data in my Database:
Id MachineName CategoryName CounterName InstanceName RawValue
11180 SERVER64 Process ID Process w3wp#2 2068
11180 SERVER64 Process Working Set w3wp#2 9310208
Now I want to achieve that if I find the value '2068' for the "ID Process" Countername then I want to retrieve the Working Set RawValue. So based on the value of ID Process I now the [InstanceName] = w3wp#2 and therefore I want the value to retrieve = 9310208
Now I tried different SQL queries:
SELECT *
FROM [dbo].[LoadTest]
WHERE [LoadTestRunId] = '11180' and [CategoryName] = 'Process' and [InstanceName] like 'w3wp%'
But I need a filter. Can anyone guide me into the right direction?
This here will help you. I used variable because you need to find a specific ID
SQL Code
declare #myt table (id int,MachineName nvarchar(50),CategoryName nvarchar(50),CounterName nvarchar(50),InstanceName nvarchar(50),RawValue int)
insert into #myt
values
(11180 ,'SERVER64','Process','ID Process','w3wp#2',2068),
(11180 ,'SERVER64','Process','Working Set','w3wp#2',9310208)
declare #FindID int
Set #FindID = 2068;
with IdProcess as (
Select * from #myt
where RawValue = #FindID and CounterName = 'ID Process'
)
Select a.ID,a.MachineName,a.CategoryName,b.CounterName,a.InstanceName,b.RawValue from IdProcess a
inner join #myt b on a.InstanceName = b.InstanceName and b.CounterName='Working Set'
SQL Code without variable based on ID and InstanceName
with IdProcess as (
Select * from #myt
where CounterName = 'ID Process'
)
Select a.ID,a.MachineName,a.CategoryName,b.CounterName,a.InstanceName,b.RawValue from IdProcess a
inner join #myt b on a.id = b.id and a.InstanceName = b.InstanceName and b.CounterName='Working Set'
SQL Code with CategoryName filter
with IdProcess as (
Select * from #myt
where CounterName = 'ID Process' and CategoryName = 'Process'
)
Select a.ID,a.MachineName,a.CategoryName,b.CounterName,a.InstanceName,b.RawValue from IdProcess a
inner join #myt b on a.id = b.id and a.InstanceName = b.InstanceName and b.CounterName='Working Set'
where b.CategoryName = 'Process'
Result
This will execute.
Select * from (SELECT ROW_NUMBER() OVER(PARTITION BY LoadTestRunId ORDER BY LoadTestRunId DESC) as row,*
FROM [dbo].[LoadTest]) t1 where row=1
with your where clause
Select * from (SELECT ROW_NUMBER() OVER(PARTITION BY LoadTestRunId ORDER BY LoadTestRunId DESC),*
FROM [dbo].[LoadTest]) t1 where t1=1
and [LoadTestRunId] = '11180' and [CategoryName] = 'Process' and [InstanceName] like 'w3wp%'

How do I use a function in a view to return only distinct union of rows?

I am trying to do a view to reference on a webpage using RadGrid control. I need to get a subset of all records in my projects table by the last entered Changedate in the Changes table per unique projectid with the Status from the Status table along with the details of the project. The ProjectId & StatusID are in the Changes table as foreign Keys.
This is my view.
CREATE VIEW [dbo].[Project-by_View]
AS
SELECT TOP (100) PERCENT
dbo.Projects.Id,
dbo.Projects.ProjectName,
dbo.Department.Name,
dbo.Designer.FName + ' ' + dbo.Designer.LName AS Designer,
dbo.Changes.ChangeDate,
dbo.Projects.DueDate,
dbo.Projects.Instructions,
dbo.Status.Description
FROM dbo.Projects
INNER JOIN dbo.Department
ON dbo.Department.ID = dbo.Projects.DeptID
INNER JOIN dbo.Designer
ON dbo.Designer.Id = dbo.Projects.DesignerID
INNER JOIN dbo.Changes
ON dbo.Changes.ProjectID = dbo.Projects.ID
INNER JOIN dbo.Status
ON dbo.Changes.StatusID = dbo.Status.Id
WHERE EXIST (SELECT *
FROM GetAllLastChangeDatebyProjectIds(0))
ORDER BY dbo.Projects.ID DESC
GO
and my function
USE [FIDO_DEV]
GO
/****** Object: UserDefinedFunction [dbo].[GetAllLastChangeDatebyProjectIds]
Script Date: 9/14/2015 4:31:22 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <Author, Geoffrey Stephens>
-- Create date: <Create Date, 09/14/20115>
-- Description: <Description, table of the Last Change Date for each Project>
-- =============================================
ALTER FUNCTION [dbo].[GetAllLastChangeDatebyProjectIds]
(
#ProjectID int
)
RETURNS TABLE
AS
RETURN
(
Select ProjectID, StatusID, ChangeDate from (
Select
ProjectID, StatusID, ChangeDate,
row_number() over(partition by ProjectID order by ChangeDate desc) as rn
from
Changes
) t
where t.rn = 1)
GO
The function works and the View work separately, but in conjunction I still get the full data set returned.
This chunk looks suspicious:
WHERE EXIST (SELECT *
FROM GetAllLastChangeDatebyProjectIds(0))
Should it not look more like:
WHERE EXIST (SELECT *
FROM GetAllLastChangeDatebyProjectIds(Projects.Id))
I haven't looked any deeper, that just jumped out at me.
Try something like this (reformatted to my preferred style)
SELECT Projects.Id,
dbo.Projects.ProjectName,
dbo.Department.Name,
dbo.Designer.FName + ' ' + dbo.Designer.LName AS Designer,
dbo.Changes.ChangeDate,
dbo.Projects.DueDate,
dbo.Projects.Instructions,
dbo.Status.Description
FROM ( SELECT ProjectID,
StatusID,
ChangeDate
FROM ( FROM ProjectID,
StatusID,
ChangeDate,
row_number() OVER (PARTITION BY ProjectID ORDER BY ChangeDate DESC) as rn
FROM Changes) t
WHERE t.rn = 1)) AS Selection
INNER JOIN dbo.Projects
ON dbo.Projects.ID = Selection.ProjectID
INNER JOIN dbo.Designer
ON dbo.Designer.Id = dbo.Projects.DesignerID
INNER JOIN dbo.Department
ON dbo.Department.ID = dbo.Projects.DeptID
INNER JOIN dbo.Changes
ON dbo.Changes.ProjectID = dbo.Projects.ID
INNER JOIN dbo.Status
ON dbo.Changes.StatusID = dbo.Status.Id
WHERE Selection.StatusID = dbo.Changes.StatusID
ORDER BY dbo.Projects.ID DESC
I reordered the Selects, so that I start with the Distinct project.ID and then do the joins. Then did the where on the Status.ID to get the latest distinct record set.
Select TOP 100 PERCENT Projects.Id, dbo.Projects.ProjectName, dbo.Department.Name, dbo.Designer.FName + ' ' + dbo.Designer.LName AS Designer, dbo.Changes.ChangeDate, dbo.Projects.DueDate, dbo.Projects.Instructions, dbo.Status.Description
From GetAllLastChangeDatebyProjectIds(0) INNER JOIN
dbo.Projects ON dbo.Projects.ID = dbo.GetAllLastChangeDatebyProjectIds.ProjectID INNER JOIN
dbo.Designer ON dbo.Designer.Id = dbo.Projects.DesignerID INNER JOIN
dbo.Department ON dbo.Department.ID = dbo.Projects.DeptID INNER JOIN
dbo.Changes ON dbo.Changes.ProjectID = dbo.Projects.ID INNER JOIN
dbo.Status ON dbo.Changes.StatusID = dbo.Status.Id
Where dbo.GetAllLastChangeDatebyProjectIds.StatusID = dbo.Changes.StatusID
ORDER BY dbo.Projects.ID DESC

Display single row of each recordset of a column with condtion

I have a query in SQL Server.
There is a temporary table #final as shown below
I want to fetch only single row of each project having Maximum EXPECTEDENDDATE.
try below one :-
Select f1.*
From #Final As f1 With (Nolock)
Join
(
Select Max(EXPECTEDENDDATE) As EXPECTEDENDDATE
,EmployeeCode
,ProjectCode
From #Final As t With (Nolock)
Group By t.EmployeeCode
,t.ProjectCode
) As f On f1.EmployeeCode = f.EmployeeCode
And f1.ProjectCode = f.ProjectCode
ANd f1.EXPECTEDENDDATE = f.EXPECTEDENDDATE
Update
Declare #final Table
(
EmployeeCode Int
,ProjectName Varchar(500)
,ExpectedStartDate Date
,ExpectedEndDate Date
,DaysAllocated Int
)
Declare #SameStartProjects Table
(
EmployeeCode Int
,ProjectName Varchar(500)
,RowNum BigInt
)
Insert Into #final(EmployeeCode,ProjectName,ExpectedStartDate,ExpectedEndDate,DaysAllocated) Values
(1149,'INT-Vibrant Web','2015-04-22','2015-05-21',14)
,(1149,'INT-Vibrant Web','2015-05-22','2015-05-31',6)
,(1149,'Praetorian Track Off','2015-03-19','2015-05-22',15)
,(1149,'Praetorian Track Off','2015-03-19','2015-06-11',20)
,(1149,'RPost Phase ||','2015-05-01','2015-05-31',20)
Insert Into #SameStartProjects(EmployeeCode,ProjectName,RowNum)
Select p.EmployeeCode
,p.ProjectName
,Row_Number() Over(Partition By p.ExpectedStartDate Order By p.ExpectedStartDate) As RowNum
From #final As p
Select s.*
From #final As s
Join
(
Select f.EmployeeCode
,f.ProjectName
,f.ExpectedStartDate
,Max(f.ExpectedEndDate) As ExpectedEndDate
,Max(sp.RowNum) As RowNum
From #final As f
Join #SameStartProjects As sp On f.EmployeeCode = sp.EmployeeCode
And f.ProjectName = sp.ProjectName
Group By f.EmployeeCode
,f.ProjectName
,f.ExpectedStartDate
) As f On s.EmployeeCode = f.EmployeeCode
And s.ProjectName = f.ProjectName
And s.ExpectedEndDate = f.ExpectedEndDate
above, #final is your #final table, and i have not taken all the attributes for example
Output:-

SQL Comparing 2 values that must be determined

I need to Find out the course with the most passes from my table tblResults.
tblResults:
StuID Course Symbol
1001 CSC101 P
1001 RNG101 F
1002 CSC101 P
1002 RNF101 F
1003 HAP101 P
1004 HAP101 P
i.e should give CSC101 (And all other courses (HAP101) with the same ammount of passes)
I have tried:
CREATE VIEW Part1 AS
SELECT NumbF
FROM
(SELECT COUNT(Course) AS NumbP,
Course
FROM tblResults
WHERE Symbol = 'P')
GROUP BY Course);
CREATE VIEW Part2 AS
SELECT MAX(NumbP) AS Maxnum
FROM Part1,
tblResults
WHERE Symbol = 'P'
GROUP BY Course;
SELECT Part1.Course
FROM Part1,
Part2
WHERE Part1.NumbP = Part2.MaxNum
But I seem to be doing something incorrectly. Please help
Something like this should work:
create view yourview as
select course, count(*) passcnt
from tblResults
where symbol = 'P'
group by course
select *
from yourview
where passcnt = (select max(passcnt) from yourview)
SQL Fiddle Demo
Note, you don't need the view, I just left it for simplicity.
SELECT Course, count(StuID) count
FROM tblResults
GROUP BY Course
HAVING count = (SELECT max(c)
FROM (SELECT count(StuID) c, Course
FROM tblResults
GROUP BY Course
WHERE Symbol = 'p'
) counts
);
You can try the SELECT below, but I haven't tested it:
SELECT selA.Course, selA.NumPass FROM (
SELECT Course, COUNT(Course) AS NumPass FROM
tblResults GROUP BY Course HAVING Symbol = 'P') AS selA
INNER JOIN (
SELECT MAX(NumPassCount) AS NumPassMax FROM (
SELECT COUNT(Course) AS NumPassCount FROM
tblResults GROUP BY Course HAVING Symbol = 'P') AS selB)
AS selC ON selA.NumPass = selC.NumPassMax
Using a couple of sub queries
SELECT Sub3.Course
FROM
(
SELECT MAX(Course) AS MaxCourseCnt
FROM
(
SELECT Course, COUNT(*) AS CourseCnt
FROM tblResults
WHERE Symbol = 'P'
GROUP BY Course
) Sub1
) Sub2
INNER JOIN
(
SELECT Course, COUNT(*) AS CourseCnt
FROM tblResults
WHERE Symbol = 'P'
GROUP BY Course
) Sub3
ON Sub2.MaxCourseCnt = Sub3.CourseCnt