Question

I am trying to interpret a query that was built in MSAccess and turn it into usable SQL for SQL Server.

Here is the statement from Access in SQL view:

SELECT CUSTFILE.CUSTNUM, 
Last(GENPOL.eff_date) AS LastOfeff_date, 
First(GENPOL.appnum) AS FirstOfAPPNUM

FROM GENPOL INNER JOIN CUSTFILE ON GENPOL.entnum = CUSTFILE.ENTNUM

GROUP BY CUSTFILE.CUSTNUM

HAVING...

ORDER BY LastGENPOL.eff_date DESC;

As we know the First() and Last() functions are invalid in SQL Server and do not work so I tried to use MIN() and MAX() functions because the table has no incremental ID field or anything. A big problem is that for instance appnum can have very strange data in it's field like:

 MTP-021106

OR

HMTP-271103

So if the last appnum inserted was HMTP-271103 and there are earlier entries into the genpol table like MTP-021106 as their appnum

Than MTP-021106 will be returned because M is greater than H.

Also, the eff_date can have the same sort of issues because the latest record could have an earlier date than the last one input.

Last(GENPOL.eff_date) AS LastOfeff_date,

Ultimately the query returns one row for each CUSTFILE.CUSTNUM that meets the HAVING criteria.

What I believe may be an answer is to use the ROW_NUMBER() function to get the results I need but have not been able to get it to work with the GROUP BY statement.

Table GENPOL:

(PK)appnum, varchar(13)
eff_date, datetime
ntnum, varchar(15)

Table CUSTFILE:

(PK)CUSTNUM, varchar(8)
ENTNUM, varchar(15)

Sample Data

CUSTNUM | LastOfeff_date | FirstOfAppnum
MI99103 | 2013-01-01 | MTP-991103
MI99104 | 2013-01-01 | MTP-991104
MI99105 | 2013-01-01 | MTP-991105
Was it helpful?

Solution

EDIT: fixed a reference to one of the columns

Based on what you've listed, something like this should work:

SELECT 
    cfile.CUSTNUM,
    aGENPOL.eff_date [LastOfeff_date],
    bGENPOL.appnum [FirstOfAPPNUM] 
FROM CUSTFILE cfile
CROSS APPLY (
    SELECT TOP 1 * 
    FROM (
        SELECT ROW_NUMBER() OVER(PARTITION BY entnum ORDER BY entnum) row, eff_date
        FROM GENPOL 
        WHERE entnum  = cfile.entnum        
    ) x
    ORDER BY row DESC
) aGENPOL 
CROSS APPLY (
    SELECT TOP 1 * 
    FROM (
        SELECT ROW_NUMBER() OVER(PARTITION BY entnum ORDER BY entnum) row, appnum
        FROM GENPOL 
        WHERE entnum  = cfile.entnum 
    ) y
    ORDER BY row
) bGENPOL

Basically, the queries in the applies will grab the top record for each situation by partitioning the table by each entnum, and then ordering it by the row number (ascending for First, descending for Last).

Since the joined queries are fairly complicated, I also chose to use a CROSS APPLY, as it essentially filters the records down before making the join.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top