SQL Pagination Query with order by

江枫思渺然 提交于 2019-12-10 10:48:10

问题


I am trying to write a query that pulls multiple fields and assigns aliases to them. One of the aliases is actually a sum total of two fields. This is actually my biggest issue because that alias is one of the possible "fields" to sort by, or else I could just take out all of the aliases and not have this issue. Anyway, I need to be able to pass in a field in which to order by programmaticly. But because I need to do pagination with SQL, I cannot use the graceful function of LIMIT and have to use a sub query.

This is where the big issue comes in. Because I absolutely HAVE to select at least 2 columns in the sub query (because I need the ID field for the limiting purpose, and the sum total alias as an order by field), I cannot use this as an "And ID Not In (sub query)" since you can only return one field in that manner. So I'll show you my code, then explain the results I am getting.

SELECT     TOP (50) dbo.tblMailList.mail_ID AS Expr1, dbo.tblMailList.mail_NameTitle AS Expr2, dbo.tblMailList.mail_FirstName AS Expr3, 
                      dbo.tblMailList.mail_LastName AS Expr4, dbo.tblMailList.mail_Company AS Expr5, dbo.tblMailList.mail_Institution AS Expr6, 
                      SUM(dbo.tblItem.item_pr + dbo.tblItem.item_premium) AS Expr7, dbo.tblMailList.mail_Comp_Art, dbo.tblMailList.mail_Comp_IndArt, 
                      dbo.tblMailList.mail_Comp_GenAm, dbo.tblMailList.mail_Comp_Fire, dbo.tblMailList.mail_Comp_Jewelry, dbo.tblMailList.mail_Comp_Ceramic, 
                      dbo.tblMailList.mail_Interest
FROM         (SELECT     TOP (50) tblMailList_1.mail_ID AS Expr1, tblMailList_1.mail_NameTitle AS Expr2, tblMailList_1.mail_FirstName AS Expr3, 
                                              tblMailList_1.mail_LastName AS Expr4, tblMailList_1.mail_Company AS Expr5, tblMailList_1.mail_Institution AS Expr6, 
                                              SUM(tblItem_1.item_pr + tblItem_1.item_premium) AS Expr7, tblMailList_1.mail_Comp_Art, tblMailList_1.mail_Comp_IndArt, 
                                              tblMailList_1.mail_Comp_GenAm, tblMailList_1.mail_Comp_Fire, tblMailList_1.mail_Comp_Jewelry, tblMailList_1.mail_Comp_Ceramic, 
                                              tblMailList_1.mail_Interest
                       FROM          dbo.tblItem AS tblItem_1 INNER JOIN
                                              dbo.tblBidder AS tblBidder_1 ON tblItem_1.item_bidder_number = tblBidder_1.bidder_number AND 
                                              tblItem_1.item_sale_id = tblBidder_1.bidder_sale_id INNER JOIN
                                              dbo.tblMailList AS tblMailList_1 ON tblBidder_1.bidder_mail_id = tblMailList_1.mail_ID
                       WHERE      (tblMailList_1.mail_Comp_Art <> '1' OR
                                              tblMailList_1.mail_Comp_Art IS NULL) AND (tblMailList_1.mail_Comp_IndArt <> '1' OR
                                              tblMailList_1.mail_Comp_IndArt IS NULL) AND (tblMailList_1.mail_Comp_GenAm <> '1' OR
                                              tblMailList_1.mail_Comp_GenAm IS NULL) AND (tblMailList_1.mail_Comp_Fire <> '1' OR
                                              tblMailList_1.mail_Comp_Fire IS NULL)
                       GROUP BY tblMailList_1.mail_Company, tblMailList_1.mail_Institution, tblMailList_1.mail_LastName, tblMailList_1.mail_FirstName, 
                                              tblMailList_1.mail_NameTitle, tblMailList_1.mail_ID, tblMailList_1.mail_Comp_Art, tblMailList_1.mail_Comp_IndArt, 
                                              tblMailList_1.mail_Comp_GenAm, tblMailList_1.mail_Comp_Fire, tblMailList_1.mail_Interest, tblMailList_1.mail_Comp_Jewelry, 
                                              tblMailList_1.mail_Comp_Ceramic
                       ORDER BY Expr7 DESC) AS tblLimiter INNER JOIN
                      dbo.tblMailList ON NOT (tblLimiter.Expr1 = dbo.tblMailList.mail_ID) INNER JOIN
                      dbo.tblBidder ON dbo.tblBidder.bidder_mail_id = dbo.tblMailList.mail_ID INNER JOIN
                      dbo.tblItem ON dbo.tblItem.item_bidder_number = dbo.tblBidder.bidder_number AND dbo.tblItem.item_sale_id = dbo.tblBidder.bidder_sale_id
WHERE     (dbo.tblMailList.mail_Comp_Art <> '1' OR
                      dbo.tblMailList.mail_Comp_Art IS NULL) AND (dbo.tblMailList.mail_Comp_IndArt <> '1' OR
                      dbo.tblMailList.mail_Comp_IndArt IS NULL) AND (dbo.tblMailList.mail_Comp_GenAm <> '1' OR
                      dbo.tblMailList.mail_Comp_GenAm IS NULL) AND (dbo.tblMailList.mail_Comp_Fire <> '1' OR
                      dbo.tblMailList.mail_Comp_Fire IS NULL) AND (NOT (dbo.tblMailList.mail_ID = tblLimiter.Expr1))
GROUP BY dbo.tblMailList.mail_Company, dbo.tblMailList.mail_Institution, dbo.tblMailList.mail_LastName, dbo.tblMailList.mail_FirstName, 
                      dbo.tblMailList.mail_NameTitle, dbo.tblMailList.mail_ID, dbo.tblMailList.mail_Comp_Art, dbo.tblMailList.mail_Comp_IndArt, 
                      dbo.tblMailList.mail_Comp_GenAm, dbo.tblMailList.mail_Comp_Fire, dbo.tblMailList.mail_Interest, dbo.tblMailList.mail_Comp_Jewelry, 
                      dbo.tblMailList.mail_Comp_Ceramic
ORDER BY Expr7 DESC

The issue with this one is that if the sub query selects top 0, nothing is returned, which was fairly obvious, but I needed to try because I've tried a lot. When 50 is selected, it returns 50 rows with large SUM totals. When 100 is selected, it returns the same 50 (because of the original top 50), but the SUM totals are twice as big...

Now I also had this to where the "FROM" statement was reversed, in the same order as what is in the sub query itself, like this:

SELECT     TOP (50) tblMailList.mail_ID AS Expr1, tblMailList.mail_NameTitle AS Expr2, tblMailList.mail_FirstName AS Expr3, 
                      tblMailList.mail_LastName AS Expr4, tblMailList.mail_Company AS Expr5, tblMailList.mail_Institution AS Expr6, 
                      SUM(tblItem.item_pr + tblItem.item_premium) AS Expr7, tblMailList.mail_Comp_Art, tblMailList.mail_Comp_IndArt, tblMailList.mail_Comp_GenAm, 
                      tblMailList.mail_Comp_Fire, tblMailList.mail_Comp_Jewelry, tblMailList.mail_Comp_Ceramic, tblMailList.mail_Interest
FROM         dbo.tblItem AS tblItem INNER JOIN
                      dbo.tblBidder AS tblBidder ON tblItem.item_bidder_number = tblBidder.bidder_number AND tblItem.item_sale_id = tblBidder.bidder_sale_id INNER JOIN
                      dbo.tblMailList AS tblMailList ON tblBidder.bidder_mail_id = tblMailList.mail_ID LEFT OUTER JOIN
                          (SELECT     TOP (50) tblMailList_1.mail_ID AS Expr1, tblMailList_1.mail_NameTitle AS Expr2, tblMailList_1.mail_FirstName AS Expr3, 
                                                   tblMailList_1.mail_LastName AS Expr4, tblMailList_1.mail_Company AS Expr5, tblMailList_1.mail_Institution AS Expr6, 
                                                   SUM(tblItem_1.item_pr + tblItem_1.item_premium) AS Expr7, tblMailList_1.mail_Comp_Art, tblMailList_1.mail_Comp_IndArt, 
                                                   tblMailList_1.mail_Comp_GenAm, tblMailList_1.mail_Comp_Fire, tblMailList_1.mail_Comp_Jewelry, tblMailList_1.mail_Comp_Ceramic, 
                                                   tblMailList_1.mail_Interest
                            FROM          dbo.tblItem AS tblItem_1 INNER JOIN
                                                   dbo.tblBidder AS tblBidder_1 ON tblItem_1.item_bidder_number = tblBidder_1.bidder_number AND 
                                                   tblItem_1.item_sale_id = tblBidder_1.bidder_sale_id INNER JOIN
                                                   dbo.tblMailList AS tblMailList_1 ON tblBidder_1.bidder_mail_id = tblMailList_1.mail_ID
                            WHERE      (tblMailList_1.mail_Comp_Art <> '1' OR
                                                   tblMailList_1.mail_Comp_Art IS NULL) AND (tblMailList_1.mail_Comp_IndArt <> '1' OR
                                                   tblMailList_1.mail_Comp_IndArt IS NULL) AND (tblMailList_1.mail_Comp_GenAm <> '1' OR
                                                   tblMailList_1.mail_Comp_GenAm IS NULL) AND (tblMailList_1.mail_Comp_Fire <> '1' OR
                                                   tblMailList_1.mail_Comp_Fire IS NULL)
                            GROUP BY tblMailList_1.mail_Company, tblMailList_1.mail_Institution, tblMailList_1.mail_LastName, tblMailList_1.mail_FirstName, 
                                                   tblMailList_1.mail_NameTitle, tblMailList_1.mail_ID, tblMailList_1.mail_Comp_Art, tblMailList_1.mail_Comp_IndArt, 
                                                   tblMailList_1.mail_Comp_GenAm, tblMailList_1.mail_Comp_Fire, tblMailList_1.mail_Interest, tblMailList_1.mail_Comp_Jewelry, 
                                                   tblMailList_1.mail_Comp_Ceramic
                            ORDER BY Expr7 DESC) AS tblLimiter ON tblLimiter.Expr1 > 0
WHERE     (tblMailList.mail_Comp_Art <> '1' OR
                      tblMailList.mail_Comp_Art IS NULL) AND (tblMailList.mail_Comp_IndArt <> '1' OR
                      tblMailList.mail_Comp_IndArt IS NULL) AND (tblMailList.mail_Comp_GenAm <> '1' OR
                      tblMailList.mail_Comp_GenAm IS NULL) AND (tblMailList.mail_Comp_Fire <> '1' OR
                      tblMailList.mail_Comp_Fire IS NULL) AND (NOT (tblMailList.mail_ID = tblLimiter.Expr1))
GROUP BY tblMailList.mail_Company, tblMailList.mail_Institution, tblMailList.mail_LastName, tblMailList.mail_FirstName, tblMailList.mail_NameTitle, 
                      tblMailList.mail_ID, tblMailList.mail_Comp_Art, tblMailList.mail_Comp_IndArt, tblMailList.mail_Comp_GenAm, tblMailList.mail_Comp_Fire, 
                      tblMailList.mail_Interest, tblMailList.mail_Comp_Jewelry, tblMailList.mail_Comp_Ceramic
ORDER BY Expr7 DESC

However, this works the exact same way as the other way (in the way the results are returned).

I really wish I could do a "AND NOT IN (sub query)", because I can make those work without an issue. But because of the SUM in Expr7, I cannot do that. And I'm a MySQL guy, so I don't know a whole lot about SQL. I hope I gave enough information. If not, just let me know. Thanks for all replies.


回答1:


Instead of using TOP 50 for your pagination use ROW_NUMBER and then use the where

WITH CTE AS (
SELECT     
           ROW_NUMBER() OVER (ORDER BY  SUM(dbo.tblItem.item_pr + dbo.tblItem.item_premium) ) RN,
           dbo.tblMailList.mail_ID AS Expr1, dbo.tblMailList.mail_NameTitle AS Expr2, dbo.tblMailList.mail_FirstName AS Expr3, 
           dbo.tblMailList.mail_LastName AS Expr4, dbo.tblMailList.mail_Company AS Expr5, dbo.tblMailList.mail_Institution AS Expr6, 
           SUM(dbo.tblItem.item_pr + dbo.tblItem.item_premium) AS Expr7, 
           dbo.tblMailList.mail_Comp_Art, dbo.tblMailList.mail_Comp_IndArt, 
           dbo.tblMailList.mail_Comp_GenAm, dbo.tblMailList.mail_Comp_Fire, dbo.tblMailList.mail_Comp_Jewelry, dbo.tblMailList.mail_Comp_Ceramic, 
 .....
)
SELECT * FROM CTE WHERE rn Between 50 and 100


来源:https://stackoverflow.com/questions/9098535/sql-pagination-query-with-order-by

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!