Reputation: 67
I have two tables TBL_CONTACT
and TBL_PHONE
that I am trying to join.
The TBL_PHONE
table contains duplicate rows for contacts with multiple phone numbers, so I am partitioning these and trying to select the first instance only.
Here is the code I have:
SELECT
(CONTACT.CONTACTID),
(CONTACT.FULLNAME),
(PHONE.contactid),
(PHONE.numberdisplay),
(row_number() OVER(PARTITION BY PHONE.Contactid ORDER BY PHONE.Contactid)) prn
FROM
"ACT2015Demo"."dbo"."TBL_CONTACT" AS CONTACT
INNER JOIN
TBL_PHONE AS PHONE
ON CONTACT.Contactid = PHONE.Contactid
WHERE
CAST(Editdate AS DATE) = CAST(GETDATE() AS DATE)
This gives the following:
CONTACTID FULLNAME CONTACTID NUMBERDISPLAY PRN
1001 Name1 1001 Tel1001 1 1
1001 Name1 1001 Tel1001 2 2
1002 Name2 1002 Tel1002 1 1
1003 Name3 1003 Tel1003 1 1
1003 Name3 1003 Tel1003 2 2
1003 Name3 1003 Tel1003 3 3
I then want to use the PRN column to limit the output to only rows with PRN = 1. I have tried the following, as this has worked for me in the past on less complex joins:
SELECT
(CONTACT.CONTACTID),
(CONTACT.FULLNAME),
(PHONE.contactid),
(PHONE.numberdisplay),
(row_number() OVER(PARTITION BY PHONE.Contactid ORDER BY PHONE.Contactid)) prn
FROM
"ACT2015Demo"."dbo"."TBL_CONTACT" AS CONTACT
INNER JOIN
TBL_PHONE AS PHONE
ON CONTACT.Contactid = PHONE.Contactid AND PRN = 1
WHERE
CAST(Editdate AS DATE) = CAST(GETDATE() AS DATE)
However, this gives me the invalid column name error for PRN
? I have also tried using PRN = 1
as part of the WHERE
with the same error.
How can I get PRN
to work as a column name and limit the output?
Upvotes: 1
Views: 5261
Reputation: 304
This error also happens when the row_number() OVER(PARTITION BY ) clause has a composite set of key fields which appear in both tables in the join. The error will not go away no-matter how the aliases are arranged or rearranged. To solve this, the identically named key columns from the joining table must be renamed in an in-line temporary table as follows. Change this:
INNER JOIN
TBL_PHONE AS PHONE
ON CONTACT.Contactid = PHONE.Contactid
... some other col_names
etc. ...
to this:
INNER JOIN (
SELECT
Contactid as PK_Contactid,
... some other col_names as PK_col_names,
etc. ...
FROM TBL_PHONE
) AS PHONE
ON CONTACT.Contactid = PHONE.PK_Contactid
... some other col_names
etc. ...
NB. and don't prefix the any col_names with table aliases in the row_number() OVER(PARTITION BY ) clause at all. Worked for me.
Upvotes: 2
Reputation: 562388
Something a bit weird and confusing for some people about SQL is that column aliases you define in the select-list cannot be referenced in the FROM
clause or WHERE
clause.
This is confusing because of the fact that column aliases appear to be defined early in the query (as the select-list is before the FROM
clause). But the order of the syntax is not the order of execution.
You can get around this by running your query as a derived table subquery:
SELECT *
FROM (
SELECT
CONTACT.CONTACTID,
CONTACT.FULLNAME,
PHONE.contactid,
PHONE.numberdisplay,
ROW_NUMBER() OVER(PARTITION BY PHONE.Contactid ORDER BY PHONE.Contactid) AS PRN
FROM
"ACT2015Demo"."dbo"."TBL_CONTACT" AS CONTACT
INNER JOIN
TBL_PHONE AS PHONE
ON CONTACT.Contactid = PHONE.Contactid
WHERE
CAST(Editdate AS DATE) = CAST(GETDATE() AS DATE)
) AS DerivedTable
WHERE PRN = 1
PS: MySQL does not support windowing functions in versions up to 5.7. It has been announced that this feature is being worked on, hopefully it will be ready in MySQL 8. I think you may have tagged your question incorrectly.
You use the schema qualifier dbo
which makes me think you are using Microsoft SQL Server or Sybase, is this correct?
Upvotes: 3
Reputation: 28900
I have tried the following, as this has worked for me in the past on less complex joins...The way you tried will never work for simple joins as well.You have to use Derived table or CTE
Select
*
from
(
SELECT
(CONTACT.CONTACTID) as concontactid,
(CONTACT.FULLNAME),
(PHONE.contactid),
(PHONE.numberdisplay),
(row_number() OVER(PARTITION BY PHONE.Contactid ORDER BY PHONE.Contactid)) prn
FROM
"ACT2015Demo"."dbo"."TBL_CONTACT" AS CONTACT
INNER JOIN
TBL_PHONE AS PHONE
ON CONTACT.Contactid = PHONE.Contactid
WHERE
CAST(Editdate AS DATE) = CAST(GETDATE() AS DATE)
) as b
where prn=1
Upvotes: 1