Is this the correct way to use UNION ALL in a stored procedure?











up vote
5
down vote

favorite
2












Is this the correct way to UNION ALL in a stored procedure?



ALTER PROCEDURE [GetHomePageObjectPageWise]
@PageIndex INT = 1
,@PageSize INT = 10
,@PageCount INT OUTPUT
,@whereStoryID varchar(2000)
,@whereAlbumID varchar(2000)
,@wherePictureID varchar(2000)
AS
BEGIN
SET NOCOUNT ON;

SELECT StoryID
, AlbumID
, StoryTitle
, NULL AS AlbumName
, (SELECT URL FROM AlbumPictures WHERE (AlbumID = dbo.Stories.AlbumID) AND (AlbumCover = 'True')) AS AlbumCover
, Votes
, NULL AS PictureId
, 'stories' AS tableName
, NEWID() AS Sort

INTO #Results1
FROM Stories WHERE StoryID IN (SELECT StringVal FROM funcListToTableInt(@whereStoryID))

SELECT NULL AS StoryID
, AlbumID
, NULL AS StoryTitle
, AlbumName
, (SELECT URL FROM AlbumPictures AS AlbumPictures_3 WHERE (AlbumID = Albums.AlbumID) AND (AlbumCover = 'True')) AS AlbumCover
, Votes
, NULL AS PictureId
, 'albums' AS tableName
, NEWID() AS Sort
INTO #Results2
FROM Albums WHERE AlbumID IN (SELECT StringVal FROM funcListToTableInt(@whereAlbumID))

SELECT NULL AS StoryID
, NULL AS AlbumID
, NULL AS StoryTitle
, NULL AS AlbumName
, URL
, Votes
, PictureID
, 'pictures' AS tableName
, NEWID() AS Sort
INTO #Results3
FROM AlbumPictures AS AlbumPictures_1
WHERE PictureID IN (SELECT StringVal FROM funcListToTableInt(@wherePictureID))

SELECT * INTO #Results4 FROM #Results1
UNION ALL
SELECT * FROM #Results2
UNION ALL
SELECT * FROM #Results3

SELECT ROW_NUMBER() OVER
(
ORDER BY [Sort] DESC
)AS RowNumber
, * INTO #Results
FROM #Results4


DECLARE @RecordCount INT
SELECT @RecordCount = COUNT(*) FROM #Results

SET @PageCount = CEILING(CAST(@RecordCount AS DECIMAL(10, 2)) / CAST(@PageSize AS DECIMAL(10, 2)))

SELECT * FROM #Results
WHERE RowNumber BETWEEN(@PageIndex -1) * @PageSize + 1 AND(((@PageIndex -1) * @PageSize + 1) + @PageSize) - 1

DROP TABLE #Results
DROP TABLE #Results1
DROP TABLE #Results2
DROP TABLE #Results3
DROP TABLE #Results4
END









share|improve this question




















  • 1




    Can you elaborate on what your question is?
    – Gordon Linoff
    Dec 30 '12 at 20:44










  • @GordonLinoff As shown in the given example, 1st i am doing 3 selects and putting the result into 3 views then i am doing union all on the 3 views. So i want to know, is this the correct way or can i optimize it in a better way?
    – user1593175
    Dec 30 '12 at 20:50






  • 1




    You're not putting the results in three views, you're putting them in three temporary tables. You're then copying that to a fourth temporary table, and copying that to a fifth temporary table. That does seem like there must be a simpler way. And you're copying all the records every time even though you'll only want 10 (adjustable) rows in the result set. As it is, though, it's hard to see what exactly you're looking for (NEWID() for a column Sort?), in order to be able to improve on your procedure. Can you show your tables, sample data, sample input parameters, and desired output?
    – user743382
    Dec 30 '12 at 21:00










  • @hvd kindly check my other question for the table structure,sample input and output.http://stackoverflow.com/questions/14071312/combining-rows-from-multiple-tables-with-different-number-of-columns/
    – user1593175
    Dec 30 '12 at 21:13










  • @user1593175 Ah, so you want a random 10 rows from any of the three tables? What are you doing with PageIndex? When you ask for page 1, and then ask for page 1 again, you won't get the same results, because you'll have re-shuffled them. That seems like it's what you want, but having PageIndex there at all seems unnecessary. I also have my doubts how you're selecting random rows, this question has more details and alternatives for that part.
    – user743382
    Dec 30 '12 at 21:22















up vote
5
down vote

favorite
2












Is this the correct way to UNION ALL in a stored procedure?



ALTER PROCEDURE [GetHomePageObjectPageWise]
@PageIndex INT = 1
,@PageSize INT = 10
,@PageCount INT OUTPUT
,@whereStoryID varchar(2000)
,@whereAlbumID varchar(2000)
,@wherePictureID varchar(2000)
AS
BEGIN
SET NOCOUNT ON;

SELECT StoryID
, AlbumID
, StoryTitle
, NULL AS AlbumName
, (SELECT URL FROM AlbumPictures WHERE (AlbumID = dbo.Stories.AlbumID) AND (AlbumCover = 'True')) AS AlbumCover
, Votes
, NULL AS PictureId
, 'stories' AS tableName
, NEWID() AS Sort

INTO #Results1
FROM Stories WHERE StoryID IN (SELECT StringVal FROM funcListToTableInt(@whereStoryID))

SELECT NULL AS StoryID
, AlbumID
, NULL AS StoryTitle
, AlbumName
, (SELECT URL FROM AlbumPictures AS AlbumPictures_3 WHERE (AlbumID = Albums.AlbumID) AND (AlbumCover = 'True')) AS AlbumCover
, Votes
, NULL AS PictureId
, 'albums' AS tableName
, NEWID() AS Sort
INTO #Results2
FROM Albums WHERE AlbumID IN (SELECT StringVal FROM funcListToTableInt(@whereAlbumID))

SELECT NULL AS StoryID
, NULL AS AlbumID
, NULL AS StoryTitle
, NULL AS AlbumName
, URL
, Votes
, PictureID
, 'pictures' AS tableName
, NEWID() AS Sort
INTO #Results3
FROM AlbumPictures AS AlbumPictures_1
WHERE PictureID IN (SELECT StringVal FROM funcListToTableInt(@wherePictureID))

SELECT * INTO #Results4 FROM #Results1
UNION ALL
SELECT * FROM #Results2
UNION ALL
SELECT * FROM #Results3

SELECT ROW_NUMBER() OVER
(
ORDER BY [Sort] DESC
)AS RowNumber
, * INTO #Results
FROM #Results4


DECLARE @RecordCount INT
SELECT @RecordCount = COUNT(*) FROM #Results

SET @PageCount = CEILING(CAST(@RecordCount AS DECIMAL(10, 2)) / CAST(@PageSize AS DECIMAL(10, 2)))

SELECT * FROM #Results
WHERE RowNumber BETWEEN(@PageIndex -1) * @PageSize + 1 AND(((@PageIndex -1) * @PageSize + 1) + @PageSize) - 1

DROP TABLE #Results
DROP TABLE #Results1
DROP TABLE #Results2
DROP TABLE #Results3
DROP TABLE #Results4
END









share|improve this question




















  • 1




    Can you elaborate on what your question is?
    – Gordon Linoff
    Dec 30 '12 at 20:44










  • @GordonLinoff As shown in the given example, 1st i am doing 3 selects and putting the result into 3 views then i am doing union all on the 3 views. So i want to know, is this the correct way or can i optimize it in a better way?
    – user1593175
    Dec 30 '12 at 20:50






  • 1




    You're not putting the results in three views, you're putting them in three temporary tables. You're then copying that to a fourth temporary table, and copying that to a fifth temporary table. That does seem like there must be a simpler way. And you're copying all the records every time even though you'll only want 10 (adjustable) rows in the result set. As it is, though, it's hard to see what exactly you're looking for (NEWID() for a column Sort?), in order to be able to improve on your procedure. Can you show your tables, sample data, sample input parameters, and desired output?
    – user743382
    Dec 30 '12 at 21:00










  • @hvd kindly check my other question for the table structure,sample input and output.http://stackoverflow.com/questions/14071312/combining-rows-from-multiple-tables-with-different-number-of-columns/
    – user1593175
    Dec 30 '12 at 21:13










  • @user1593175 Ah, so you want a random 10 rows from any of the three tables? What are you doing with PageIndex? When you ask for page 1, and then ask for page 1 again, you won't get the same results, because you'll have re-shuffled them. That seems like it's what you want, but having PageIndex there at all seems unnecessary. I also have my doubts how you're selecting random rows, this question has more details and alternatives for that part.
    – user743382
    Dec 30 '12 at 21:22













up vote
5
down vote

favorite
2









up vote
5
down vote

favorite
2






2





Is this the correct way to UNION ALL in a stored procedure?



ALTER PROCEDURE [GetHomePageObjectPageWise]
@PageIndex INT = 1
,@PageSize INT = 10
,@PageCount INT OUTPUT
,@whereStoryID varchar(2000)
,@whereAlbumID varchar(2000)
,@wherePictureID varchar(2000)
AS
BEGIN
SET NOCOUNT ON;

SELECT StoryID
, AlbumID
, StoryTitle
, NULL AS AlbumName
, (SELECT URL FROM AlbumPictures WHERE (AlbumID = dbo.Stories.AlbumID) AND (AlbumCover = 'True')) AS AlbumCover
, Votes
, NULL AS PictureId
, 'stories' AS tableName
, NEWID() AS Sort

INTO #Results1
FROM Stories WHERE StoryID IN (SELECT StringVal FROM funcListToTableInt(@whereStoryID))

SELECT NULL AS StoryID
, AlbumID
, NULL AS StoryTitle
, AlbumName
, (SELECT URL FROM AlbumPictures AS AlbumPictures_3 WHERE (AlbumID = Albums.AlbumID) AND (AlbumCover = 'True')) AS AlbumCover
, Votes
, NULL AS PictureId
, 'albums' AS tableName
, NEWID() AS Sort
INTO #Results2
FROM Albums WHERE AlbumID IN (SELECT StringVal FROM funcListToTableInt(@whereAlbumID))

SELECT NULL AS StoryID
, NULL AS AlbumID
, NULL AS StoryTitle
, NULL AS AlbumName
, URL
, Votes
, PictureID
, 'pictures' AS tableName
, NEWID() AS Sort
INTO #Results3
FROM AlbumPictures AS AlbumPictures_1
WHERE PictureID IN (SELECT StringVal FROM funcListToTableInt(@wherePictureID))

SELECT * INTO #Results4 FROM #Results1
UNION ALL
SELECT * FROM #Results2
UNION ALL
SELECT * FROM #Results3

SELECT ROW_NUMBER() OVER
(
ORDER BY [Sort] DESC
)AS RowNumber
, * INTO #Results
FROM #Results4


DECLARE @RecordCount INT
SELECT @RecordCount = COUNT(*) FROM #Results

SET @PageCount = CEILING(CAST(@RecordCount AS DECIMAL(10, 2)) / CAST(@PageSize AS DECIMAL(10, 2)))

SELECT * FROM #Results
WHERE RowNumber BETWEEN(@PageIndex -1) * @PageSize + 1 AND(((@PageIndex -1) * @PageSize + 1) + @PageSize) - 1

DROP TABLE #Results
DROP TABLE #Results1
DROP TABLE #Results2
DROP TABLE #Results3
DROP TABLE #Results4
END









share|improve this question















Is this the correct way to UNION ALL in a stored procedure?



ALTER PROCEDURE [GetHomePageObjectPageWise]
@PageIndex INT = 1
,@PageSize INT = 10
,@PageCount INT OUTPUT
,@whereStoryID varchar(2000)
,@whereAlbumID varchar(2000)
,@wherePictureID varchar(2000)
AS
BEGIN
SET NOCOUNT ON;

SELECT StoryID
, AlbumID
, StoryTitle
, NULL AS AlbumName
, (SELECT URL FROM AlbumPictures WHERE (AlbumID = dbo.Stories.AlbumID) AND (AlbumCover = 'True')) AS AlbumCover
, Votes
, NULL AS PictureId
, 'stories' AS tableName
, NEWID() AS Sort

INTO #Results1
FROM Stories WHERE StoryID IN (SELECT StringVal FROM funcListToTableInt(@whereStoryID))

SELECT NULL AS StoryID
, AlbumID
, NULL AS StoryTitle
, AlbumName
, (SELECT URL FROM AlbumPictures AS AlbumPictures_3 WHERE (AlbumID = Albums.AlbumID) AND (AlbumCover = 'True')) AS AlbumCover
, Votes
, NULL AS PictureId
, 'albums' AS tableName
, NEWID() AS Sort
INTO #Results2
FROM Albums WHERE AlbumID IN (SELECT StringVal FROM funcListToTableInt(@whereAlbumID))

SELECT NULL AS StoryID
, NULL AS AlbumID
, NULL AS StoryTitle
, NULL AS AlbumName
, URL
, Votes
, PictureID
, 'pictures' AS tableName
, NEWID() AS Sort
INTO #Results3
FROM AlbumPictures AS AlbumPictures_1
WHERE PictureID IN (SELECT StringVal FROM funcListToTableInt(@wherePictureID))

SELECT * INTO #Results4 FROM #Results1
UNION ALL
SELECT * FROM #Results2
UNION ALL
SELECT * FROM #Results3

SELECT ROW_NUMBER() OVER
(
ORDER BY [Sort] DESC
)AS RowNumber
, * INTO #Results
FROM #Results4


DECLARE @RecordCount INT
SELECT @RecordCount = COUNT(*) FROM #Results

SET @PageCount = CEILING(CAST(@RecordCount AS DECIMAL(10, 2)) / CAST(@PageSize AS DECIMAL(10, 2)))

SELECT * FROM #Results
WHERE RowNumber BETWEEN(@PageIndex -1) * @PageSize + 1 AND(((@PageIndex -1) * @PageSize + 1) + @PageSize) - 1

DROP TABLE #Results
DROP TABLE #Results1
DROP TABLE #Results2
DROP TABLE #Results3
DROP TABLE #Results4
END






sql sql-server stored-procedures sql-server-2008-r2 union






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Dec 30 '12 at 21:44









marc_s

567k12810981249




567k12810981249










asked Dec 30 '12 at 20:20









user1593175

162314




162314








  • 1




    Can you elaborate on what your question is?
    – Gordon Linoff
    Dec 30 '12 at 20:44










  • @GordonLinoff As shown in the given example, 1st i am doing 3 selects and putting the result into 3 views then i am doing union all on the 3 views. So i want to know, is this the correct way or can i optimize it in a better way?
    – user1593175
    Dec 30 '12 at 20:50






  • 1




    You're not putting the results in three views, you're putting them in three temporary tables. You're then copying that to a fourth temporary table, and copying that to a fifth temporary table. That does seem like there must be a simpler way. And you're copying all the records every time even though you'll only want 10 (adjustable) rows in the result set. As it is, though, it's hard to see what exactly you're looking for (NEWID() for a column Sort?), in order to be able to improve on your procedure. Can you show your tables, sample data, sample input parameters, and desired output?
    – user743382
    Dec 30 '12 at 21:00










  • @hvd kindly check my other question for the table structure,sample input and output.http://stackoverflow.com/questions/14071312/combining-rows-from-multiple-tables-with-different-number-of-columns/
    – user1593175
    Dec 30 '12 at 21:13










  • @user1593175 Ah, so you want a random 10 rows from any of the three tables? What are you doing with PageIndex? When you ask for page 1, and then ask for page 1 again, you won't get the same results, because you'll have re-shuffled them. That seems like it's what you want, but having PageIndex there at all seems unnecessary. I also have my doubts how you're selecting random rows, this question has more details and alternatives for that part.
    – user743382
    Dec 30 '12 at 21:22














  • 1




    Can you elaborate on what your question is?
    – Gordon Linoff
    Dec 30 '12 at 20:44










  • @GordonLinoff As shown in the given example, 1st i am doing 3 selects and putting the result into 3 views then i am doing union all on the 3 views. So i want to know, is this the correct way or can i optimize it in a better way?
    – user1593175
    Dec 30 '12 at 20:50






  • 1




    You're not putting the results in three views, you're putting them in three temporary tables. You're then copying that to a fourth temporary table, and copying that to a fifth temporary table. That does seem like there must be a simpler way. And you're copying all the records every time even though you'll only want 10 (adjustable) rows in the result set. As it is, though, it's hard to see what exactly you're looking for (NEWID() for a column Sort?), in order to be able to improve on your procedure. Can you show your tables, sample data, sample input parameters, and desired output?
    – user743382
    Dec 30 '12 at 21:00










  • @hvd kindly check my other question for the table structure,sample input and output.http://stackoverflow.com/questions/14071312/combining-rows-from-multiple-tables-with-different-number-of-columns/
    – user1593175
    Dec 30 '12 at 21:13










  • @user1593175 Ah, so you want a random 10 rows from any of the three tables? What are you doing with PageIndex? When you ask for page 1, and then ask for page 1 again, you won't get the same results, because you'll have re-shuffled them. That seems like it's what you want, but having PageIndex there at all seems unnecessary. I also have my doubts how you're selecting random rows, this question has more details and alternatives for that part.
    – user743382
    Dec 30 '12 at 21:22








1




1




Can you elaborate on what your question is?
– Gordon Linoff
Dec 30 '12 at 20:44




Can you elaborate on what your question is?
– Gordon Linoff
Dec 30 '12 at 20:44












@GordonLinoff As shown in the given example, 1st i am doing 3 selects and putting the result into 3 views then i am doing union all on the 3 views. So i want to know, is this the correct way or can i optimize it in a better way?
– user1593175
Dec 30 '12 at 20:50




@GordonLinoff As shown in the given example, 1st i am doing 3 selects and putting the result into 3 views then i am doing union all on the 3 views. So i want to know, is this the correct way or can i optimize it in a better way?
– user1593175
Dec 30 '12 at 20:50




1




1




You're not putting the results in three views, you're putting them in three temporary tables. You're then copying that to a fourth temporary table, and copying that to a fifth temporary table. That does seem like there must be a simpler way. And you're copying all the records every time even though you'll only want 10 (adjustable) rows in the result set. As it is, though, it's hard to see what exactly you're looking for (NEWID() for a column Sort?), in order to be able to improve on your procedure. Can you show your tables, sample data, sample input parameters, and desired output?
– user743382
Dec 30 '12 at 21:00




You're not putting the results in three views, you're putting them in three temporary tables. You're then copying that to a fourth temporary table, and copying that to a fifth temporary table. That does seem like there must be a simpler way. And you're copying all the records every time even though you'll only want 10 (adjustable) rows in the result set. As it is, though, it's hard to see what exactly you're looking for (NEWID() for a column Sort?), in order to be able to improve on your procedure. Can you show your tables, sample data, sample input parameters, and desired output?
– user743382
Dec 30 '12 at 21:00












@hvd kindly check my other question for the table structure,sample input and output.http://stackoverflow.com/questions/14071312/combining-rows-from-multiple-tables-with-different-number-of-columns/
– user1593175
Dec 30 '12 at 21:13




@hvd kindly check my other question for the table structure,sample input and output.http://stackoverflow.com/questions/14071312/combining-rows-from-multiple-tables-with-different-number-of-columns/
– user1593175
Dec 30 '12 at 21:13












@user1593175 Ah, so you want a random 10 rows from any of the three tables? What are you doing with PageIndex? When you ask for page 1, and then ask for page 1 again, you won't get the same results, because you'll have re-shuffled them. That seems like it's what you want, but having PageIndex there at all seems unnecessary. I also have my doubts how you're selecting random rows, this question has more details and alternatives for that part.
– user743382
Dec 30 '12 at 21:22




@user1593175 Ah, so you want a random 10 rows from any of the three tables? What are you doing with PageIndex? When you ask for page 1, and then ask for page 1 again, you won't get the same results, because you'll have re-shuffled them. That seems like it's what you want, but having PageIndex there at all seems unnecessary. I also have my doubts how you're selecting random rows, this question has more details and alternatives for that part.
– user743382
Dec 30 '12 at 21:22












2 Answers
2






active

oldest

votes

















up vote
3
down vote



accepted










These days I like to use non-materialized CTEs rather than temp tables - although in certain circumstances (say the data needs an index) I'll use temp tables.



Mainly lots of cosmetic stuff I'd change really all in the way of hopefully making it more readable in the future (this is not tested as I do not have a copy of your data)



ALTER PROCEDURE [GetHomePageObjectPageWise]
@PageIndex INT = 1
,@PageSize INT = 10
,@PageCount INT OUTPUT
,@whereStoryID VARCHAR(2000)
,@whereAlbumID VARCHAR(2000)
,@wherePictureID VARCHAR(2000)
AS
BEGIN
SET NOCOUNT ON;

WITH Results1 AS
(
SELECT
StoryID,
AlbumID,
StoryTitle,
[AlbumName] = NULL,
[AlbumCover] =
(
SELECT URL
FROM AlbumPictures
WHERE (AlbumID = dbo.Stories.AlbumID) AND (AlbumCover = 'True')
),
Votes,
[PictureId] = NULL,
[tableName] = 'stories',
[Sort] = NEWID()
FROM Stories
WHERE
StoryID IN
(
SELECT StringVal
FROM funcListToTableInt(@whereStoryID)
)
)
, Results2 AS
(
SELECT
[StoryID] = NULL ,
AlbumID,
[StoryTitle] NULL,
AlbumName,
[AlbumCover] =
(
SELECT URL
FROM AlbumPictures AS AlbumPictures_3 --<<<DO YOU NEED THIS ALIAS?
WHERE (AlbumID = Albums.AlbumID) AND (AlbumCover = 'True')
),
Votes,
[PictureId] = NULL,
[tableName] = 'albums',
[Sort] = NEWID()
FROM Albums
WHERE
AlbumID IN
(
SELECT StringVal
FROM funcListToTableInt(@whereAlbumID)
)
)
, Result3 AS
(
SELECT
[StoryID] = NULL,
[AlbumID] = NULL,
[StoryTitle] = NULL,
[AlbumName] = NULL,
URL,
Votes,
PictureID,
[tableName] = 'pictures',
[Sort] = NEWID()
FROM AlbumPictures --AS AlbumPictures_1 <<<DO YOU NEED THIS ALIAS?
WHERE
PictureID IN
(
SELECT StringVal
FROM funcListToTableInt(@wherePictureID)
)
)
, Result4 AS
(
SELECT * FROM Results1 UNION ALL
SELECT * FROM Results2 UNION ALL
SELECT * FROM Results3
)
, Results AS
(
SELECT
[RowNumber] = ROW_NUMBER() OVER (ORDER BY [Sort] DESC),
x.*
FROM Results4 x
)
SELECT *
FROM Results
WHERE RowNumber BETWEEN(@PageIndex -1) * @PageSize + 1 AND(((@PageIndex -1) * @PageSize + 1) + @PageSize) - 1;
DECLARE @RecordCount INT = @@RowCount;

SET @PageCount = CEILING(CAST(@RecordCount AS DECIMAL(10, 2)) / CAST(@PageSize AS DECIMAL(10, 2)));

END


I'm generally use Aaron Bertrand's suggestions for writing Stored Procedures this blog post is my checklist and the template I use to try to unify the style I use with all my Sprocs:



https://sqlblog.org/2008/10/30/my-stored-procedure-best-practices-checklist





I think as Gordon suggested you could move lots of the logic out of the stored procedure and create a VIEW like this:



CREATE VIEW [console].[vw_mySimpleView]
AS

BEGIN
SET NOCOUNT ON;

WITH Results1 AS
(
SELECT
StoryID,
AlbumID,
StoryTitle,
[AlbumName] = NULL,
[AlbumCover] =
(
SELECT URL
FROM AlbumPictures
WHERE (AlbumID = dbo.Stories.AlbumID) AND (AlbumCover = 'True')
),
Votes,
[PictureId] = NULL,
[tableName] = 'stories',
[Sort] = NEWID()
FROM Stories
)
, Results2 AS
(
SELECT
[StoryID] = NULL ,
AlbumID,
[StoryTitle] NULL,
AlbumName,
[AlbumCover] =
(
SELECT URL
FROM AlbumPictures
WHERE (AlbumID = Albums.AlbumID) AND (AlbumCover = 'True')
),
Votes,
[PictureId] = NULL,
[tableName] = 'albums',
[Sort] = NEWID()
FROM Albums
)
, Result3 AS
(
SELECT
[StoryID] = NULL,
[AlbumID] = NULL,
[StoryTitle] = NULL,
[AlbumName] = NULL,
URL,
Votes,
PictureID,
[tableName] = 'pictures',
[Sort] = NEWID()
FROM AlbumPictures
)
, Result4 AS
(
SELECT * FROM Results1 UNION ALL
SELECT * FROM Results2 UNION ALL
SELECT * FROM Results3
)
SELECT *
FROM Results4;

GO


Then the Sproc would be a lot shorter:



ALTER PROCEDURE [GetHomePageObjectPageWise]
@PageIndex INT = 1
,@PageSize INT = 10
,@PageCount INT OUTPUT
,@whereStoryID VARCHAR(2000)
,@whereAlbumID VARCHAR(2000)
,@wherePictureID VARCHAR(2000)
AS
BEGIN
SET NOCOUNT ON;

SELECT *
FROM
(
SELECT
[RowNumber] = ROW_NUMBER() OVER (ORDER BY [Sort] DESC),
x.*
FROM
(
SELECT *
FROM [dbo].[vw_mySimpleView]
WHERE
StoryID IN
(
SELECT StringVal
FROM funcListToTableInt(@whereStoryID)
)
OR
AlbumID IN
(
SELECT StringVal
FROM funcListToTableInt(@whereAlbumID)
)
) x
)
WHERE RowNumber BETWEEN(@PageIndex -1) * @PageSize + 1 AND(((@PageIndex -1) * @PageSize + 1) + @PageSize) - 1;
DECLARE @RecordCount INT = @@RowCount;

SET @PageCount = CEILING(CAST(@RecordCount AS DECIMAL(10, 2)) / CAST(@PageSize AS DECIMAL(10, 2)));


END





share|improve this answer























  • you have used Result3 twice and you also use Result4..but i guess you have not declared Result4 anywhere..is that correct?
    – user1593175
    Dec 30 '12 at 22:15












  • typo - hopefully better now
    – whytheq
    Dec 30 '12 at 22:19










  • thanks for your time and effort. essentially there is no difference between my and your solution other than readability?
    – user1593175
    Dec 30 '12 at 22:21










  • readability via CTEs and layout. I think I did this delaration in one DECLARE @RecordCount INT = (SELECT COUNT(*) cnt FROM Results); and I got rid of some of the table aliases as they didn't seem necessary. I added semi-colons as they will be required in the future.
    – whytheq
    Dec 30 '12 at 22:24










  • Great.Thanks.You are a nice man. +1 and accepting yours as answer. Is there any way i can skip the procedure and do the same thing in dynamic sql?
    – user1593175
    Dec 30 '12 at 22:31


















up vote
3
down vote













Here are some comments:



(1) I prefer table valued variables (declare @Results as table . . .) rather than temporary tables.



(2) In general, it is probably better to write a single query rather than separate queries. So, you can eliminate the intermediate results tables anyway. SQL engines are designed to optimize execution paths. Give them a chance to work. That said, sometimes they get things wrong and intermediate tables are desirable/necessary.



(3) Your sort is ok, but you do need to be care. If Sort has duplicate values you run the risk of getting repeated values and different iterations will cause problems.



(4) Since you are really just returning results from a query, why not just define the query (perhaps as a view) and eliminate the stored procedure entirely? The stored procedure makes it unlikely that SQL Server will cache the results for paging purposes.



(5) I also wonder if you can remove the function calls in the from clause, since those can also negatively affect performance.






share|improve this answer

















  • 1




    @MartinSmith . . . As usual, you are correct, and I've learned something new. Thank you.
    – Gordon Linoff
    Dec 30 '12 at 21:07










  • Thanks for the great answer. Can you please elaborate point 2 and 4? Do you mind giving me a code snippet for point 4?
    – user1593175
    Dec 30 '12 at 21:09










  • still waiting for your reply
    – user1593175
    Dec 30 '12 at 22:22










  • @user1593175 SO is an amazing resource - sometimes you get the correct ideas from here but then you need to play with them and then maybe come back with further questions
    – whytheq
    Jan 2 '13 at 10:19










  • +1 for several avenues for the user to explore
    – whytheq
    Jan 2 '13 at 10:55











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f14094304%2fis-this-the-correct-way-to-use-union-all-in-a-stored-procedure%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
3
down vote



accepted










These days I like to use non-materialized CTEs rather than temp tables - although in certain circumstances (say the data needs an index) I'll use temp tables.



Mainly lots of cosmetic stuff I'd change really all in the way of hopefully making it more readable in the future (this is not tested as I do not have a copy of your data)



ALTER PROCEDURE [GetHomePageObjectPageWise]
@PageIndex INT = 1
,@PageSize INT = 10
,@PageCount INT OUTPUT
,@whereStoryID VARCHAR(2000)
,@whereAlbumID VARCHAR(2000)
,@wherePictureID VARCHAR(2000)
AS
BEGIN
SET NOCOUNT ON;

WITH Results1 AS
(
SELECT
StoryID,
AlbumID,
StoryTitle,
[AlbumName] = NULL,
[AlbumCover] =
(
SELECT URL
FROM AlbumPictures
WHERE (AlbumID = dbo.Stories.AlbumID) AND (AlbumCover = 'True')
),
Votes,
[PictureId] = NULL,
[tableName] = 'stories',
[Sort] = NEWID()
FROM Stories
WHERE
StoryID IN
(
SELECT StringVal
FROM funcListToTableInt(@whereStoryID)
)
)
, Results2 AS
(
SELECT
[StoryID] = NULL ,
AlbumID,
[StoryTitle] NULL,
AlbumName,
[AlbumCover] =
(
SELECT URL
FROM AlbumPictures AS AlbumPictures_3 --<<<DO YOU NEED THIS ALIAS?
WHERE (AlbumID = Albums.AlbumID) AND (AlbumCover = 'True')
),
Votes,
[PictureId] = NULL,
[tableName] = 'albums',
[Sort] = NEWID()
FROM Albums
WHERE
AlbumID IN
(
SELECT StringVal
FROM funcListToTableInt(@whereAlbumID)
)
)
, Result3 AS
(
SELECT
[StoryID] = NULL,
[AlbumID] = NULL,
[StoryTitle] = NULL,
[AlbumName] = NULL,
URL,
Votes,
PictureID,
[tableName] = 'pictures',
[Sort] = NEWID()
FROM AlbumPictures --AS AlbumPictures_1 <<<DO YOU NEED THIS ALIAS?
WHERE
PictureID IN
(
SELECT StringVal
FROM funcListToTableInt(@wherePictureID)
)
)
, Result4 AS
(
SELECT * FROM Results1 UNION ALL
SELECT * FROM Results2 UNION ALL
SELECT * FROM Results3
)
, Results AS
(
SELECT
[RowNumber] = ROW_NUMBER() OVER (ORDER BY [Sort] DESC),
x.*
FROM Results4 x
)
SELECT *
FROM Results
WHERE RowNumber BETWEEN(@PageIndex -1) * @PageSize + 1 AND(((@PageIndex -1) * @PageSize + 1) + @PageSize) - 1;
DECLARE @RecordCount INT = @@RowCount;

SET @PageCount = CEILING(CAST(@RecordCount AS DECIMAL(10, 2)) / CAST(@PageSize AS DECIMAL(10, 2)));

END


I'm generally use Aaron Bertrand's suggestions for writing Stored Procedures this blog post is my checklist and the template I use to try to unify the style I use with all my Sprocs:



https://sqlblog.org/2008/10/30/my-stored-procedure-best-practices-checklist





I think as Gordon suggested you could move lots of the logic out of the stored procedure and create a VIEW like this:



CREATE VIEW [console].[vw_mySimpleView]
AS

BEGIN
SET NOCOUNT ON;

WITH Results1 AS
(
SELECT
StoryID,
AlbumID,
StoryTitle,
[AlbumName] = NULL,
[AlbumCover] =
(
SELECT URL
FROM AlbumPictures
WHERE (AlbumID = dbo.Stories.AlbumID) AND (AlbumCover = 'True')
),
Votes,
[PictureId] = NULL,
[tableName] = 'stories',
[Sort] = NEWID()
FROM Stories
)
, Results2 AS
(
SELECT
[StoryID] = NULL ,
AlbumID,
[StoryTitle] NULL,
AlbumName,
[AlbumCover] =
(
SELECT URL
FROM AlbumPictures
WHERE (AlbumID = Albums.AlbumID) AND (AlbumCover = 'True')
),
Votes,
[PictureId] = NULL,
[tableName] = 'albums',
[Sort] = NEWID()
FROM Albums
)
, Result3 AS
(
SELECT
[StoryID] = NULL,
[AlbumID] = NULL,
[StoryTitle] = NULL,
[AlbumName] = NULL,
URL,
Votes,
PictureID,
[tableName] = 'pictures',
[Sort] = NEWID()
FROM AlbumPictures
)
, Result4 AS
(
SELECT * FROM Results1 UNION ALL
SELECT * FROM Results2 UNION ALL
SELECT * FROM Results3
)
SELECT *
FROM Results4;

GO


Then the Sproc would be a lot shorter:



ALTER PROCEDURE [GetHomePageObjectPageWise]
@PageIndex INT = 1
,@PageSize INT = 10
,@PageCount INT OUTPUT
,@whereStoryID VARCHAR(2000)
,@whereAlbumID VARCHAR(2000)
,@wherePictureID VARCHAR(2000)
AS
BEGIN
SET NOCOUNT ON;

SELECT *
FROM
(
SELECT
[RowNumber] = ROW_NUMBER() OVER (ORDER BY [Sort] DESC),
x.*
FROM
(
SELECT *
FROM [dbo].[vw_mySimpleView]
WHERE
StoryID IN
(
SELECT StringVal
FROM funcListToTableInt(@whereStoryID)
)
OR
AlbumID IN
(
SELECT StringVal
FROM funcListToTableInt(@whereAlbumID)
)
) x
)
WHERE RowNumber BETWEEN(@PageIndex -1) * @PageSize + 1 AND(((@PageIndex -1) * @PageSize + 1) + @PageSize) - 1;
DECLARE @RecordCount INT = @@RowCount;

SET @PageCount = CEILING(CAST(@RecordCount AS DECIMAL(10, 2)) / CAST(@PageSize AS DECIMAL(10, 2)));


END





share|improve this answer























  • you have used Result3 twice and you also use Result4..but i guess you have not declared Result4 anywhere..is that correct?
    – user1593175
    Dec 30 '12 at 22:15












  • typo - hopefully better now
    – whytheq
    Dec 30 '12 at 22:19










  • thanks for your time and effort. essentially there is no difference between my and your solution other than readability?
    – user1593175
    Dec 30 '12 at 22:21










  • readability via CTEs and layout. I think I did this delaration in one DECLARE @RecordCount INT = (SELECT COUNT(*) cnt FROM Results); and I got rid of some of the table aliases as they didn't seem necessary. I added semi-colons as they will be required in the future.
    – whytheq
    Dec 30 '12 at 22:24










  • Great.Thanks.You are a nice man. +1 and accepting yours as answer. Is there any way i can skip the procedure and do the same thing in dynamic sql?
    – user1593175
    Dec 30 '12 at 22:31















up vote
3
down vote



accepted










These days I like to use non-materialized CTEs rather than temp tables - although in certain circumstances (say the data needs an index) I'll use temp tables.



Mainly lots of cosmetic stuff I'd change really all in the way of hopefully making it more readable in the future (this is not tested as I do not have a copy of your data)



ALTER PROCEDURE [GetHomePageObjectPageWise]
@PageIndex INT = 1
,@PageSize INT = 10
,@PageCount INT OUTPUT
,@whereStoryID VARCHAR(2000)
,@whereAlbumID VARCHAR(2000)
,@wherePictureID VARCHAR(2000)
AS
BEGIN
SET NOCOUNT ON;

WITH Results1 AS
(
SELECT
StoryID,
AlbumID,
StoryTitle,
[AlbumName] = NULL,
[AlbumCover] =
(
SELECT URL
FROM AlbumPictures
WHERE (AlbumID = dbo.Stories.AlbumID) AND (AlbumCover = 'True')
),
Votes,
[PictureId] = NULL,
[tableName] = 'stories',
[Sort] = NEWID()
FROM Stories
WHERE
StoryID IN
(
SELECT StringVal
FROM funcListToTableInt(@whereStoryID)
)
)
, Results2 AS
(
SELECT
[StoryID] = NULL ,
AlbumID,
[StoryTitle] NULL,
AlbumName,
[AlbumCover] =
(
SELECT URL
FROM AlbumPictures AS AlbumPictures_3 --<<<DO YOU NEED THIS ALIAS?
WHERE (AlbumID = Albums.AlbumID) AND (AlbumCover = 'True')
),
Votes,
[PictureId] = NULL,
[tableName] = 'albums',
[Sort] = NEWID()
FROM Albums
WHERE
AlbumID IN
(
SELECT StringVal
FROM funcListToTableInt(@whereAlbumID)
)
)
, Result3 AS
(
SELECT
[StoryID] = NULL,
[AlbumID] = NULL,
[StoryTitle] = NULL,
[AlbumName] = NULL,
URL,
Votes,
PictureID,
[tableName] = 'pictures',
[Sort] = NEWID()
FROM AlbumPictures --AS AlbumPictures_1 <<<DO YOU NEED THIS ALIAS?
WHERE
PictureID IN
(
SELECT StringVal
FROM funcListToTableInt(@wherePictureID)
)
)
, Result4 AS
(
SELECT * FROM Results1 UNION ALL
SELECT * FROM Results2 UNION ALL
SELECT * FROM Results3
)
, Results AS
(
SELECT
[RowNumber] = ROW_NUMBER() OVER (ORDER BY [Sort] DESC),
x.*
FROM Results4 x
)
SELECT *
FROM Results
WHERE RowNumber BETWEEN(@PageIndex -1) * @PageSize + 1 AND(((@PageIndex -1) * @PageSize + 1) + @PageSize) - 1;
DECLARE @RecordCount INT = @@RowCount;

SET @PageCount = CEILING(CAST(@RecordCount AS DECIMAL(10, 2)) / CAST(@PageSize AS DECIMAL(10, 2)));

END


I'm generally use Aaron Bertrand's suggestions for writing Stored Procedures this blog post is my checklist and the template I use to try to unify the style I use with all my Sprocs:



https://sqlblog.org/2008/10/30/my-stored-procedure-best-practices-checklist





I think as Gordon suggested you could move lots of the logic out of the stored procedure and create a VIEW like this:



CREATE VIEW [console].[vw_mySimpleView]
AS

BEGIN
SET NOCOUNT ON;

WITH Results1 AS
(
SELECT
StoryID,
AlbumID,
StoryTitle,
[AlbumName] = NULL,
[AlbumCover] =
(
SELECT URL
FROM AlbumPictures
WHERE (AlbumID = dbo.Stories.AlbumID) AND (AlbumCover = 'True')
),
Votes,
[PictureId] = NULL,
[tableName] = 'stories',
[Sort] = NEWID()
FROM Stories
)
, Results2 AS
(
SELECT
[StoryID] = NULL ,
AlbumID,
[StoryTitle] NULL,
AlbumName,
[AlbumCover] =
(
SELECT URL
FROM AlbumPictures
WHERE (AlbumID = Albums.AlbumID) AND (AlbumCover = 'True')
),
Votes,
[PictureId] = NULL,
[tableName] = 'albums',
[Sort] = NEWID()
FROM Albums
)
, Result3 AS
(
SELECT
[StoryID] = NULL,
[AlbumID] = NULL,
[StoryTitle] = NULL,
[AlbumName] = NULL,
URL,
Votes,
PictureID,
[tableName] = 'pictures',
[Sort] = NEWID()
FROM AlbumPictures
)
, Result4 AS
(
SELECT * FROM Results1 UNION ALL
SELECT * FROM Results2 UNION ALL
SELECT * FROM Results3
)
SELECT *
FROM Results4;

GO


Then the Sproc would be a lot shorter:



ALTER PROCEDURE [GetHomePageObjectPageWise]
@PageIndex INT = 1
,@PageSize INT = 10
,@PageCount INT OUTPUT
,@whereStoryID VARCHAR(2000)
,@whereAlbumID VARCHAR(2000)
,@wherePictureID VARCHAR(2000)
AS
BEGIN
SET NOCOUNT ON;

SELECT *
FROM
(
SELECT
[RowNumber] = ROW_NUMBER() OVER (ORDER BY [Sort] DESC),
x.*
FROM
(
SELECT *
FROM [dbo].[vw_mySimpleView]
WHERE
StoryID IN
(
SELECT StringVal
FROM funcListToTableInt(@whereStoryID)
)
OR
AlbumID IN
(
SELECT StringVal
FROM funcListToTableInt(@whereAlbumID)
)
) x
)
WHERE RowNumber BETWEEN(@PageIndex -1) * @PageSize + 1 AND(((@PageIndex -1) * @PageSize + 1) + @PageSize) - 1;
DECLARE @RecordCount INT = @@RowCount;

SET @PageCount = CEILING(CAST(@RecordCount AS DECIMAL(10, 2)) / CAST(@PageSize AS DECIMAL(10, 2)));


END





share|improve this answer























  • you have used Result3 twice and you also use Result4..but i guess you have not declared Result4 anywhere..is that correct?
    – user1593175
    Dec 30 '12 at 22:15












  • typo - hopefully better now
    – whytheq
    Dec 30 '12 at 22:19










  • thanks for your time and effort. essentially there is no difference between my and your solution other than readability?
    – user1593175
    Dec 30 '12 at 22:21










  • readability via CTEs and layout. I think I did this delaration in one DECLARE @RecordCount INT = (SELECT COUNT(*) cnt FROM Results); and I got rid of some of the table aliases as they didn't seem necessary. I added semi-colons as they will be required in the future.
    – whytheq
    Dec 30 '12 at 22:24










  • Great.Thanks.You are a nice man. +1 and accepting yours as answer. Is there any way i can skip the procedure and do the same thing in dynamic sql?
    – user1593175
    Dec 30 '12 at 22:31













up vote
3
down vote



accepted







up vote
3
down vote



accepted






These days I like to use non-materialized CTEs rather than temp tables - although in certain circumstances (say the data needs an index) I'll use temp tables.



Mainly lots of cosmetic stuff I'd change really all in the way of hopefully making it more readable in the future (this is not tested as I do not have a copy of your data)



ALTER PROCEDURE [GetHomePageObjectPageWise]
@PageIndex INT = 1
,@PageSize INT = 10
,@PageCount INT OUTPUT
,@whereStoryID VARCHAR(2000)
,@whereAlbumID VARCHAR(2000)
,@wherePictureID VARCHAR(2000)
AS
BEGIN
SET NOCOUNT ON;

WITH Results1 AS
(
SELECT
StoryID,
AlbumID,
StoryTitle,
[AlbumName] = NULL,
[AlbumCover] =
(
SELECT URL
FROM AlbumPictures
WHERE (AlbumID = dbo.Stories.AlbumID) AND (AlbumCover = 'True')
),
Votes,
[PictureId] = NULL,
[tableName] = 'stories',
[Sort] = NEWID()
FROM Stories
WHERE
StoryID IN
(
SELECT StringVal
FROM funcListToTableInt(@whereStoryID)
)
)
, Results2 AS
(
SELECT
[StoryID] = NULL ,
AlbumID,
[StoryTitle] NULL,
AlbumName,
[AlbumCover] =
(
SELECT URL
FROM AlbumPictures AS AlbumPictures_3 --<<<DO YOU NEED THIS ALIAS?
WHERE (AlbumID = Albums.AlbumID) AND (AlbumCover = 'True')
),
Votes,
[PictureId] = NULL,
[tableName] = 'albums',
[Sort] = NEWID()
FROM Albums
WHERE
AlbumID IN
(
SELECT StringVal
FROM funcListToTableInt(@whereAlbumID)
)
)
, Result3 AS
(
SELECT
[StoryID] = NULL,
[AlbumID] = NULL,
[StoryTitle] = NULL,
[AlbumName] = NULL,
URL,
Votes,
PictureID,
[tableName] = 'pictures',
[Sort] = NEWID()
FROM AlbumPictures --AS AlbumPictures_1 <<<DO YOU NEED THIS ALIAS?
WHERE
PictureID IN
(
SELECT StringVal
FROM funcListToTableInt(@wherePictureID)
)
)
, Result4 AS
(
SELECT * FROM Results1 UNION ALL
SELECT * FROM Results2 UNION ALL
SELECT * FROM Results3
)
, Results AS
(
SELECT
[RowNumber] = ROW_NUMBER() OVER (ORDER BY [Sort] DESC),
x.*
FROM Results4 x
)
SELECT *
FROM Results
WHERE RowNumber BETWEEN(@PageIndex -1) * @PageSize + 1 AND(((@PageIndex -1) * @PageSize + 1) + @PageSize) - 1;
DECLARE @RecordCount INT = @@RowCount;

SET @PageCount = CEILING(CAST(@RecordCount AS DECIMAL(10, 2)) / CAST(@PageSize AS DECIMAL(10, 2)));

END


I'm generally use Aaron Bertrand's suggestions for writing Stored Procedures this blog post is my checklist and the template I use to try to unify the style I use with all my Sprocs:



https://sqlblog.org/2008/10/30/my-stored-procedure-best-practices-checklist





I think as Gordon suggested you could move lots of the logic out of the stored procedure and create a VIEW like this:



CREATE VIEW [console].[vw_mySimpleView]
AS

BEGIN
SET NOCOUNT ON;

WITH Results1 AS
(
SELECT
StoryID,
AlbumID,
StoryTitle,
[AlbumName] = NULL,
[AlbumCover] =
(
SELECT URL
FROM AlbumPictures
WHERE (AlbumID = dbo.Stories.AlbumID) AND (AlbumCover = 'True')
),
Votes,
[PictureId] = NULL,
[tableName] = 'stories',
[Sort] = NEWID()
FROM Stories
)
, Results2 AS
(
SELECT
[StoryID] = NULL ,
AlbumID,
[StoryTitle] NULL,
AlbumName,
[AlbumCover] =
(
SELECT URL
FROM AlbumPictures
WHERE (AlbumID = Albums.AlbumID) AND (AlbumCover = 'True')
),
Votes,
[PictureId] = NULL,
[tableName] = 'albums',
[Sort] = NEWID()
FROM Albums
)
, Result3 AS
(
SELECT
[StoryID] = NULL,
[AlbumID] = NULL,
[StoryTitle] = NULL,
[AlbumName] = NULL,
URL,
Votes,
PictureID,
[tableName] = 'pictures',
[Sort] = NEWID()
FROM AlbumPictures
)
, Result4 AS
(
SELECT * FROM Results1 UNION ALL
SELECT * FROM Results2 UNION ALL
SELECT * FROM Results3
)
SELECT *
FROM Results4;

GO


Then the Sproc would be a lot shorter:



ALTER PROCEDURE [GetHomePageObjectPageWise]
@PageIndex INT = 1
,@PageSize INT = 10
,@PageCount INT OUTPUT
,@whereStoryID VARCHAR(2000)
,@whereAlbumID VARCHAR(2000)
,@wherePictureID VARCHAR(2000)
AS
BEGIN
SET NOCOUNT ON;

SELECT *
FROM
(
SELECT
[RowNumber] = ROW_NUMBER() OVER (ORDER BY [Sort] DESC),
x.*
FROM
(
SELECT *
FROM [dbo].[vw_mySimpleView]
WHERE
StoryID IN
(
SELECT StringVal
FROM funcListToTableInt(@whereStoryID)
)
OR
AlbumID IN
(
SELECT StringVal
FROM funcListToTableInt(@whereAlbumID)
)
) x
)
WHERE RowNumber BETWEEN(@PageIndex -1) * @PageSize + 1 AND(((@PageIndex -1) * @PageSize + 1) + @PageSize) - 1;
DECLARE @RecordCount INT = @@RowCount;

SET @PageCount = CEILING(CAST(@RecordCount AS DECIMAL(10, 2)) / CAST(@PageSize AS DECIMAL(10, 2)));


END





share|improve this answer














These days I like to use non-materialized CTEs rather than temp tables - although in certain circumstances (say the data needs an index) I'll use temp tables.



Mainly lots of cosmetic stuff I'd change really all in the way of hopefully making it more readable in the future (this is not tested as I do not have a copy of your data)



ALTER PROCEDURE [GetHomePageObjectPageWise]
@PageIndex INT = 1
,@PageSize INT = 10
,@PageCount INT OUTPUT
,@whereStoryID VARCHAR(2000)
,@whereAlbumID VARCHAR(2000)
,@wherePictureID VARCHAR(2000)
AS
BEGIN
SET NOCOUNT ON;

WITH Results1 AS
(
SELECT
StoryID,
AlbumID,
StoryTitle,
[AlbumName] = NULL,
[AlbumCover] =
(
SELECT URL
FROM AlbumPictures
WHERE (AlbumID = dbo.Stories.AlbumID) AND (AlbumCover = 'True')
),
Votes,
[PictureId] = NULL,
[tableName] = 'stories',
[Sort] = NEWID()
FROM Stories
WHERE
StoryID IN
(
SELECT StringVal
FROM funcListToTableInt(@whereStoryID)
)
)
, Results2 AS
(
SELECT
[StoryID] = NULL ,
AlbumID,
[StoryTitle] NULL,
AlbumName,
[AlbumCover] =
(
SELECT URL
FROM AlbumPictures AS AlbumPictures_3 --<<<DO YOU NEED THIS ALIAS?
WHERE (AlbumID = Albums.AlbumID) AND (AlbumCover = 'True')
),
Votes,
[PictureId] = NULL,
[tableName] = 'albums',
[Sort] = NEWID()
FROM Albums
WHERE
AlbumID IN
(
SELECT StringVal
FROM funcListToTableInt(@whereAlbumID)
)
)
, Result3 AS
(
SELECT
[StoryID] = NULL,
[AlbumID] = NULL,
[StoryTitle] = NULL,
[AlbumName] = NULL,
URL,
Votes,
PictureID,
[tableName] = 'pictures',
[Sort] = NEWID()
FROM AlbumPictures --AS AlbumPictures_1 <<<DO YOU NEED THIS ALIAS?
WHERE
PictureID IN
(
SELECT StringVal
FROM funcListToTableInt(@wherePictureID)
)
)
, Result4 AS
(
SELECT * FROM Results1 UNION ALL
SELECT * FROM Results2 UNION ALL
SELECT * FROM Results3
)
, Results AS
(
SELECT
[RowNumber] = ROW_NUMBER() OVER (ORDER BY [Sort] DESC),
x.*
FROM Results4 x
)
SELECT *
FROM Results
WHERE RowNumber BETWEEN(@PageIndex -1) * @PageSize + 1 AND(((@PageIndex -1) * @PageSize + 1) + @PageSize) - 1;
DECLARE @RecordCount INT = @@RowCount;

SET @PageCount = CEILING(CAST(@RecordCount AS DECIMAL(10, 2)) / CAST(@PageSize AS DECIMAL(10, 2)));

END


I'm generally use Aaron Bertrand's suggestions for writing Stored Procedures this blog post is my checklist and the template I use to try to unify the style I use with all my Sprocs:



https://sqlblog.org/2008/10/30/my-stored-procedure-best-practices-checklist





I think as Gordon suggested you could move lots of the logic out of the stored procedure and create a VIEW like this:



CREATE VIEW [console].[vw_mySimpleView]
AS

BEGIN
SET NOCOUNT ON;

WITH Results1 AS
(
SELECT
StoryID,
AlbumID,
StoryTitle,
[AlbumName] = NULL,
[AlbumCover] =
(
SELECT URL
FROM AlbumPictures
WHERE (AlbumID = dbo.Stories.AlbumID) AND (AlbumCover = 'True')
),
Votes,
[PictureId] = NULL,
[tableName] = 'stories',
[Sort] = NEWID()
FROM Stories
)
, Results2 AS
(
SELECT
[StoryID] = NULL ,
AlbumID,
[StoryTitle] NULL,
AlbumName,
[AlbumCover] =
(
SELECT URL
FROM AlbumPictures
WHERE (AlbumID = Albums.AlbumID) AND (AlbumCover = 'True')
),
Votes,
[PictureId] = NULL,
[tableName] = 'albums',
[Sort] = NEWID()
FROM Albums
)
, Result3 AS
(
SELECT
[StoryID] = NULL,
[AlbumID] = NULL,
[StoryTitle] = NULL,
[AlbumName] = NULL,
URL,
Votes,
PictureID,
[tableName] = 'pictures',
[Sort] = NEWID()
FROM AlbumPictures
)
, Result4 AS
(
SELECT * FROM Results1 UNION ALL
SELECT * FROM Results2 UNION ALL
SELECT * FROM Results3
)
SELECT *
FROM Results4;

GO


Then the Sproc would be a lot shorter:



ALTER PROCEDURE [GetHomePageObjectPageWise]
@PageIndex INT = 1
,@PageSize INT = 10
,@PageCount INT OUTPUT
,@whereStoryID VARCHAR(2000)
,@whereAlbumID VARCHAR(2000)
,@wherePictureID VARCHAR(2000)
AS
BEGIN
SET NOCOUNT ON;

SELECT *
FROM
(
SELECT
[RowNumber] = ROW_NUMBER() OVER (ORDER BY [Sort] DESC),
x.*
FROM
(
SELECT *
FROM [dbo].[vw_mySimpleView]
WHERE
StoryID IN
(
SELECT StringVal
FROM funcListToTableInt(@whereStoryID)
)
OR
AlbumID IN
(
SELECT StringVal
FROM funcListToTableInt(@whereAlbumID)
)
) x
)
WHERE RowNumber BETWEEN(@PageIndex -1) * @PageSize + 1 AND(((@PageIndex -1) * @PageSize + 1) + @PageSize) - 1;
DECLARE @RecordCount INT = @@RowCount;

SET @PageCount = CEILING(CAST(@RecordCount AS DECIMAL(10, 2)) / CAST(@PageSize AS DECIMAL(10, 2)));


END






share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 11 at 13:57









Aaron Bertrand

206k27361402




206k27361402










answered Dec 30 '12 at 22:08









whytheq

19.3k46121217




19.3k46121217












  • you have used Result3 twice and you also use Result4..but i guess you have not declared Result4 anywhere..is that correct?
    – user1593175
    Dec 30 '12 at 22:15












  • typo - hopefully better now
    – whytheq
    Dec 30 '12 at 22:19










  • thanks for your time and effort. essentially there is no difference between my and your solution other than readability?
    – user1593175
    Dec 30 '12 at 22:21










  • readability via CTEs and layout. I think I did this delaration in one DECLARE @RecordCount INT = (SELECT COUNT(*) cnt FROM Results); and I got rid of some of the table aliases as they didn't seem necessary. I added semi-colons as they will be required in the future.
    – whytheq
    Dec 30 '12 at 22:24










  • Great.Thanks.You are a nice man. +1 and accepting yours as answer. Is there any way i can skip the procedure and do the same thing in dynamic sql?
    – user1593175
    Dec 30 '12 at 22:31


















  • you have used Result3 twice and you also use Result4..but i guess you have not declared Result4 anywhere..is that correct?
    – user1593175
    Dec 30 '12 at 22:15












  • typo - hopefully better now
    – whytheq
    Dec 30 '12 at 22:19










  • thanks for your time and effort. essentially there is no difference between my and your solution other than readability?
    – user1593175
    Dec 30 '12 at 22:21










  • readability via CTEs and layout. I think I did this delaration in one DECLARE @RecordCount INT = (SELECT COUNT(*) cnt FROM Results); and I got rid of some of the table aliases as they didn't seem necessary. I added semi-colons as they will be required in the future.
    – whytheq
    Dec 30 '12 at 22:24










  • Great.Thanks.You are a nice man. +1 and accepting yours as answer. Is there any way i can skip the procedure and do the same thing in dynamic sql?
    – user1593175
    Dec 30 '12 at 22:31
















you have used Result3 twice and you also use Result4..but i guess you have not declared Result4 anywhere..is that correct?
– user1593175
Dec 30 '12 at 22:15






you have used Result3 twice and you also use Result4..but i guess you have not declared Result4 anywhere..is that correct?
– user1593175
Dec 30 '12 at 22:15














typo - hopefully better now
– whytheq
Dec 30 '12 at 22:19




typo - hopefully better now
– whytheq
Dec 30 '12 at 22:19












thanks for your time and effort. essentially there is no difference between my and your solution other than readability?
– user1593175
Dec 30 '12 at 22:21




thanks for your time and effort. essentially there is no difference between my and your solution other than readability?
– user1593175
Dec 30 '12 at 22:21












readability via CTEs and layout. I think I did this delaration in one DECLARE @RecordCount INT = (SELECT COUNT(*) cnt FROM Results); and I got rid of some of the table aliases as they didn't seem necessary. I added semi-colons as they will be required in the future.
– whytheq
Dec 30 '12 at 22:24




readability via CTEs and layout. I think I did this delaration in one DECLARE @RecordCount INT = (SELECT COUNT(*) cnt FROM Results); and I got rid of some of the table aliases as they didn't seem necessary. I added semi-colons as they will be required in the future.
– whytheq
Dec 30 '12 at 22:24












Great.Thanks.You are a nice man. +1 and accepting yours as answer. Is there any way i can skip the procedure and do the same thing in dynamic sql?
– user1593175
Dec 30 '12 at 22:31




Great.Thanks.You are a nice man. +1 and accepting yours as answer. Is there any way i can skip the procedure and do the same thing in dynamic sql?
– user1593175
Dec 30 '12 at 22:31












up vote
3
down vote













Here are some comments:



(1) I prefer table valued variables (declare @Results as table . . .) rather than temporary tables.



(2) In general, it is probably better to write a single query rather than separate queries. So, you can eliminate the intermediate results tables anyway. SQL engines are designed to optimize execution paths. Give them a chance to work. That said, sometimes they get things wrong and intermediate tables are desirable/necessary.



(3) Your sort is ok, but you do need to be care. If Sort has duplicate values you run the risk of getting repeated values and different iterations will cause problems.



(4) Since you are really just returning results from a query, why not just define the query (perhaps as a view) and eliminate the stored procedure entirely? The stored procedure makes it unlikely that SQL Server will cache the results for paging purposes.



(5) I also wonder if you can remove the function calls in the from clause, since those can also negatively affect performance.






share|improve this answer

















  • 1




    @MartinSmith . . . As usual, you are correct, and I've learned something new. Thank you.
    – Gordon Linoff
    Dec 30 '12 at 21:07










  • Thanks for the great answer. Can you please elaborate point 2 and 4? Do you mind giving me a code snippet for point 4?
    – user1593175
    Dec 30 '12 at 21:09










  • still waiting for your reply
    – user1593175
    Dec 30 '12 at 22:22










  • @user1593175 SO is an amazing resource - sometimes you get the correct ideas from here but then you need to play with them and then maybe come back with further questions
    – whytheq
    Jan 2 '13 at 10:19










  • +1 for several avenues for the user to explore
    – whytheq
    Jan 2 '13 at 10:55















up vote
3
down vote













Here are some comments:



(1) I prefer table valued variables (declare @Results as table . . .) rather than temporary tables.



(2) In general, it is probably better to write a single query rather than separate queries. So, you can eliminate the intermediate results tables anyway. SQL engines are designed to optimize execution paths. Give them a chance to work. That said, sometimes they get things wrong and intermediate tables are desirable/necessary.



(3) Your sort is ok, but you do need to be care. If Sort has duplicate values you run the risk of getting repeated values and different iterations will cause problems.



(4) Since you are really just returning results from a query, why not just define the query (perhaps as a view) and eliminate the stored procedure entirely? The stored procedure makes it unlikely that SQL Server will cache the results for paging purposes.



(5) I also wonder if you can remove the function calls in the from clause, since those can also negatively affect performance.






share|improve this answer

















  • 1




    @MartinSmith . . . As usual, you are correct, and I've learned something new. Thank you.
    – Gordon Linoff
    Dec 30 '12 at 21:07










  • Thanks for the great answer. Can you please elaborate point 2 and 4? Do you mind giving me a code snippet for point 4?
    – user1593175
    Dec 30 '12 at 21:09










  • still waiting for your reply
    – user1593175
    Dec 30 '12 at 22:22










  • @user1593175 SO is an amazing resource - sometimes you get the correct ideas from here but then you need to play with them and then maybe come back with further questions
    – whytheq
    Jan 2 '13 at 10:19










  • +1 for several avenues for the user to explore
    – whytheq
    Jan 2 '13 at 10:55













up vote
3
down vote










up vote
3
down vote









Here are some comments:



(1) I prefer table valued variables (declare @Results as table . . .) rather than temporary tables.



(2) In general, it is probably better to write a single query rather than separate queries. So, you can eliminate the intermediate results tables anyway. SQL engines are designed to optimize execution paths. Give them a chance to work. That said, sometimes they get things wrong and intermediate tables are desirable/necessary.



(3) Your sort is ok, but you do need to be care. If Sort has duplicate values you run the risk of getting repeated values and different iterations will cause problems.



(4) Since you are really just returning results from a query, why not just define the query (perhaps as a view) and eliminate the stored procedure entirely? The stored procedure makes it unlikely that SQL Server will cache the results for paging purposes.



(5) I also wonder if you can remove the function calls in the from clause, since those can also negatively affect performance.






share|improve this answer












Here are some comments:



(1) I prefer table valued variables (declare @Results as table . . .) rather than temporary tables.



(2) In general, it is probably better to write a single query rather than separate queries. So, you can eliminate the intermediate results tables anyway. SQL engines are designed to optimize execution paths. Give them a chance to work. That said, sometimes they get things wrong and intermediate tables are desirable/necessary.



(3) Your sort is ok, but you do need to be care. If Sort has duplicate values you run the risk of getting repeated values and different iterations will cause problems.



(4) Since you are really just returning results from a query, why not just define the query (perhaps as a view) and eliminate the stored procedure entirely? The stored procedure makes it unlikely that SQL Server will cache the results for paging purposes.



(5) I also wonder if you can remove the function calls in the from clause, since those can also negatively affect performance.







share|improve this answer












share|improve this answer



share|improve this answer










answered Dec 30 '12 at 21:02









Gordon Linoff

750k34286393




750k34286393








  • 1




    @MartinSmith . . . As usual, you are correct, and I've learned something new. Thank you.
    – Gordon Linoff
    Dec 30 '12 at 21:07










  • Thanks for the great answer. Can you please elaborate point 2 and 4? Do you mind giving me a code snippet for point 4?
    – user1593175
    Dec 30 '12 at 21:09










  • still waiting for your reply
    – user1593175
    Dec 30 '12 at 22:22










  • @user1593175 SO is an amazing resource - sometimes you get the correct ideas from here but then you need to play with them and then maybe come back with further questions
    – whytheq
    Jan 2 '13 at 10:19










  • +1 for several avenues for the user to explore
    – whytheq
    Jan 2 '13 at 10:55














  • 1




    @MartinSmith . . . As usual, you are correct, and I've learned something new. Thank you.
    – Gordon Linoff
    Dec 30 '12 at 21:07










  • Thanks for the great answer. Can you please elaborate point 2 and 4? Do you mind giving me a code snippet for point 4?
    – user1593175
    Dec 30 '12 at 21:09










  • still waiting for your reply
    – user1593175
    Dec 30 '12 at 22:22










  • @user1593175 SO is an amazing resource - sometimes you get the correct ideas from here but then you need to play with them and then maybe come back with further questions
    – whytheq
    Jan 2 '13 at 10:19










  • +1 for several avenues for the user to explore
    – whytheq
    Jan 2 '13 at 10:55








1




1




@MartinSmith . . . As usual, you are correct, and I've learned something new. Thank you.
– Gordon Linoff
Dec 30 '12 at 21:07




@MartinSmith . . . As usual, you are correct, and I've learned something new. Thank you.
– Gordon Linoff
Dec 30 '12 at 21:07












Thanks for the great answer. Can you please elaborate point 2 and 4? Do you mind giving me a code snippet for point 4?
– user1593175
Dec 30 '12 at 21:09




Thanks for the great answer. Can you please elaborate point 2 and 4? Do you mind giving me a code snippet for point 4?
– user1593175
Dec 30 '12 at 21:09












still waiting for your reply
– user1593175
Dec 30 '12 at 22:22




still waiting for your reply
– user1593175
Dec 30 '12 at 22:22












@user1593175 SO is an amazing resource - sometimes you get the correct ideas from here but then you need to play with them and then maybe come back with further questions
– whytheq
Jan 2 '13 at 10:19




@user1593175 SO is an amazing resource - sometimes you get the correct ideas from here but then you need to play with them and then maybe come back with further questions
– whytheq
Jan 2 '13 at 10:19












+1 for several avenues for the user to explore
– whytheq
Jan 2 '13 at 10:55




+1 for several avenues for the user to explore
– whytheq
Jan 2 '13 at 10:55


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f14094304%2fis-this-the-correct-way-to-use-union-all-in-a-stored-procedure%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Guess what letter conforming each word

Port of Spain

Run scheduled task as local user group (not BUILTIN)