Over(Partition by ) Column not being recognized. Invalid column - sql

When I execute the following query:
SELECT
MH.MemberKey,
ROW_NUMBER() OVER(PARTITION BY MH.MemberKey ORDER BY MH.MemberKey ASC) AS "NewRow",
MH.FirstName,
MH.LastName,
MH.BirthDate,
MH.AddressLine1,
MH.AddressLine2,
MH.AddressLine3,
MH.City AS MemberCity,
MH.StateCode AS MemberState,
MH.ZipCode AS MemberZip
FROM MembershipHistory MH
WHERE NewRow = 1;
I get the following error:
Msg 207, Level 16, State 1, Line 36
Invalid column name 'NewRow'.
I tried keeping AS, removing AS, removing ""....nothing seems to work. It just wont recognize the column.

The evaluation of the row_number function in the SELECT is done after the WHERE clause has been applied so the alias is not recognized, you can use a subquery to get the result:
select
MH.MemberKey,
NewRow,
MH.FirstName,
MH.LastName,
MH.BirthDate,
MH.AddressLine1,
MH.AddressLine2,
MH.AddressLine3,
MH.City AS MemberCity,
MH.StateCode AS MemberState,
MH.ZipCode AS MemberZip
from
(
SELECT
MH.MemberKey,
ROW_NUMBER() OVER(PARTITION BY MH.MemberKey ORDER BY MH.MemberKey ASC) AS NewRow,
MH.FirstName,
MH.LastName,
MH.BirthDate,
MH.AddressLine1,
MH.AddressLine2,
MH.AddressLine3,
MH.City AS MemberCity,
MH.StateCode AS MemberState,
MH.ZipCode AS MemberZip
FROM MembershipHistory MH
) MH
WHERE NewRow = 1;
In SQL Server the Logical Processinf Order of the SELECT Statement is (from MSDN Docs):
FROM
ON
JOIN
WHERE
GROUP BY
WITH CUBE or WITH ROLLUP
HAVING
SELECT
DISTINCT
ORDER BY
TOP

Another approach is to use a CTE:
;WITH x AS (SELECT MH.whatever, ROW_NUMBER() ... AS NewRow FROM dbo.table)
SELECT * FROM x WHERE NewRow = 1;

Related

I am trying to create a table in teradata and it doesn't work

I am trying to create a table in teradata with sql, but I keep getting the following error:
CREATE TABLE FAILED. [3707] Syntax error, expected something like a name or a Unicode delimited identifier or an 'UDFCALLNAME' keyword or a 'SELECT' keyword or '(' between '(' and the 'WITH' keyword
My goal is to create a table that takes the maximum data, named "verwerkingdatum" in my code for every "contract_nr". Without the create table statement it worked just fine. Now I'm trying to create a table out of this. But I get the error above.
Here is my code:
create table mi_temp.beslagrek_saldo as
(SEL * FROM( WITH x AS
(
SELECT geld_contract_event_id, contract_nr, contract_soort_code,
contract_hergebruik_volgnr,
verwerking_datum,
event_dat,
valuta_code,
saldo_na_muteren_orig,
saldo_na_muteren_eur,
saldo_na_muteren_dc_ind,
valuta_datum,
geld_transactie_soort_code,
tegenrekening_nr,
tegenrekening_naam,
boek_datum,
storno_ind,
mutatie_bedrag_orig,
mutatie_bedrag_eur,
mutatie_bedrag_dc_ind,
soort_overboeking,
tegenrekening_nr_num,
automaat_transactie_type,
automaat_id,
automaat_datum,
automaat_tijd,
ROW_NUMBER() OVER (PARTITION BY contract_nr ORDER BY
verwerking_datum DESC) AS RowNum
FROM MI_VM_Ldm.vgeld_contract_event
WHERE verwerking_datum >= 1181201 AND verwerking_datum <= 1181231
)
SELECT geld_contract_event_id, contract_nr, contract_soort_code,
contract_hergebruik_volgnr,
verwerking_datum,
event_dat,
valuta_code,
saldo_na_muteren_orig,
saldo_na_muteren_eur,
saldo_na_muteren_dc_ind,
valuta_datum,
geld_transactie_soort_code,
tegenrekening_nr,
tegenrekening_naam,
boek_datum,
storno_ind,
mutatie_bedrag_orig,
mutatie_bedrag_eur,
mutatie_bedrag_dc_ind,
soort_overboeking,
tegenrekening_nr_num,
automaat_transactie_type,
automaat_id,
automaat_datum,
automaat_tijd
FROM X
WHERE RowNum = 1))
If I'm reading your post correctly, are you are trying to is filter your select so that your rownum = 1. You can just use qualify to accomplish that.
create table foo as (
SELECT geld_contract_event_id, contract_nr, contract_soort_code,
contract_hergebruik_volgnr,
verwerking_datum,
event_dat,
valuta_code,
saldo_na_muteren_orig,
saldo_na_muteren_eur,
saldo_na_muteren_dc_ind,
valuta_datum,
geld_transactie_soort_code,
tegenrekening_nr,
tegenrekening_naam,
boek_datum,
storno_ind,
mutatie_bedrag_orig,
mutatie_bedrag_eur,
mutatie_bedrag_dc_ind,
soort_overboeking,
tegenrekening_nr_num,
automaat_transactie_type,
automaat_id,
automaat_datum,
automaat_tijd
from
MI_VM_Ldm.vgeld_contract_event
WHERE verwerking_datum >= 1181201 AND verwerking_datum <= 1181231
qualify ROW_NUMBER() OVER (PARTITION BY contract_nr ORDER BY verwerking_datum DESC) =1
) with data;

Update table with another column in the same table

I have a table like this
Test_order
Order Num Order ID Prev Order ID
987Y7OP89 919325 0
987Y7OP90 1006626 919325
987Y7OP91 1029350 1006626
987Y7OP92 1756689 0
987Y7OP93 1756690 0
987Y7OP94 1950100 1756690
987Y7OP95 1977570 1950100
987Y7OP96 2160462 1977570
987Y7OP97 2288982 2160462
Target table should be like below,
Order Num Order ID Prev Order ID
987Y7OP89 919325 0
987Y7OP90 1006626 919325
987Y7OP91 1029350 1006626
987Y7OP92 1756689 1029350
987Y7OP93 1756690 1756689
987Y7OP94 1950100 1756690
987Y7OP95 1977570 1950100
987Y7OP96 2160462 1977570
987Y7OP97 2288982 2160462
987Y7OP97 2288900 2288982
Prev Order ID should be updated with the Order ID from the previous record from the same table.
I'm trying to create a dummy data set and update..but it's not working..
WITH A AS
(SELECT ORDER_NUM, ORDER_ID, PRIOR_ORDER_ID,ROWNUM RID1 FROM TEST_ORDER),B AS (SELECT ORDER_NUM, ORDER_ID, PRIOR_ORDER_ID,ROWNUM+1 RID2 FROM TEST_ORDER)
SELECT A.ORDER_NUM,B.ORDER_ID,A.PRIOR_ORDER_ID,B.PRIOR_ORDER_ID FROM A,B WHERE RID1 = RID2
You could use Oracles Analytical Functions (also called Window functions) to pick up the value from the previous order:
UPDATE Test_Order
SET ORDERID = LAG(ORDERID, 1, 0) OVER (ORDER BY ORDERNUM ASC)
WHERE PrevOrderId = 0
See here for the documentation on LAG()
In sql-server you cannot use window function in update statement, not positive but don't think so in Oracle either. Anyway to get around that you can just update a cte as follows.
WITH cte AS (
SELECT
*
,NewPreviousOrderId = LAG(OrderId,1,0) OVER (ORDER BY OrderNum)
FROM
TableName
)
UPDATE cte
SET PrevOrderId = NewPreviousOrderId
And if you want to stick with the ROW_NUMBER route you were going this would be the way of doing it.
;WITH cte AS (
SELECT
*
,ROW_NUMBER() OVER (ORDER BY OrderNum) AS RowNum
FROM
TableName
)
UPDATE c1
SET PrevOrderId = c2.OrderId
FROM
cte c1
INNER JOIN cte c2
ON (c1.RowNum - 1) = c2.RowNum

SQL ROW_NUMBER OVER syntax

I have this:
SELECT ROW_NUMBER() OVER (ORDER BY vwmain.ch) as RowNumber,
vwmain.vehicleref,vwmain.capid,
vwmain.manufacturer,vwmain.model,vwmain.derivative,
vwmain.isspecial,
vwmain.created,vwmain.updated,vwmain.stocklevel,
vwmain.[type],
vwmain.ch,vwmain.co2,vwmain.mpg,vwmain.term,vwmain.milespa
FROM vwMain_LATEST vwmain
INNER JOIN HomepageFeatured
on vwMain.vehicleref = homepageFeatured.vehicleref
WHERE homepagefeatured.siteskinid = 1
AND homepagefeatured.Rotator = 1
AND RowNumber = 1
ORDER BY homepagefeatured.orderby
It fails on "Invalid column name RowNumber"
Not sure how to prefix it to access it?
Thanks
You can't reference the field like that. You can however use a subquery or a common-table-expression:
Here's a subquery:
SELECT *
FROM (
SELECT ROW_NUMBER() OVER (ORDER BY vwmain.ch) as RowNumber,
vwmain.vehicleref,vwmain.capid,
vwmain.manufacturer,vwmain.model,vwmain.derivative,
vwmain.isspecial,
vwmain.created,vwmain.updated,vwmain.stocklevel,
vwmain.[type],
vwmain.ch,vwmain.co2,vwmain.mpg,vwmain.term,vwmain.milespa,
homepagefeatured.orderby
FROM vwMain_LATEST vwmain
INNER JOIN HomepageFeatured on vwMain.vehicleref = homepageFeatured.vehicleref
WHERE homepagefeatured.siteskinid = 1
AND homepagefeatured.Rotator = 1
) T
WHERE RowNumber = 1
ORDER BY orderby
Rereading your query, since you aren't partitioning by any fields, the order by at the end is useless (it contradicts the order of the ranking function). You're probably better off using top 1...
Using top:
SELECT top 1 vwmain.vehicleref,vwmain.capid,
vwmain.manufacturer,vwmain.model,vwmain.derivative,
vwmain.isspecial,
vwmain.created,vwmain.updated,vwmain.stocklevel,
vwmain.[type],
vwmain.ch,vwmain.co2,vwmain.mpg,vwmain.term,vwmain.milespa,
homepagefeatured.orderby
FROM vwMain_LATEST vwmain
INNER JOIN HomepageFeatured on vwMain.vehicleref = homepageFeatured.vehicleref
WHERE homepagefeatured.siteskinid = 1
AND homepagefeatured.Rotator = 1
ORDER BY homepagefeatured.orderby
(EDIT: This answer is a nearby pitfall. I leave it for documentation.)
Have a look here: Referring to a Column Alias in a WHERE Clause
This is the same situation.
It is a matter of how the sql query is parsed/compiled internally, so your field alias names are not known at the time the where clause is interpreted. Therefore you might try, in reference to the example above:
SELECT ROW_NUMBER() OVER (ORDER BY vwmain.ch) as RowNumber,
vwmain.vehicleref,vwmain.capid, vwmain.manufacturer,vwmain.model,vwmain.derivative, vwmain.isspecial,vwmain.created,vwmain.updated,vwmain.stocklevel, vwmain.[type],
vwmain.ch,vwmain.co2,vwmain.mpg,vwmain.term,vwmain.milespa
FROM vwMain_LATEST vwmain
INNER JOIN HomepageFeatured on vwMain.vehicleref = homepageFeatured.vehicleref
WHERE homepagefeatured.siteskinid = 1
AND homepagefeatured.Rotator = 1
AND ROW_NUMBER() OVER (ORDER BY vwmain.ch) = 1
ORDER BY homepagefeatured.orderby
Thus you see your expression in the select statement is exactly reused in the where clause.

ORA-00936: missing expression oracle

I have this query
SELECT DAL_ROWNOTABLE.DAL_ID FROM
(
SELECT ticket.id AS "DAL_ID", ROWNUMBER ( Order By ticket.id ) AS "DAL_ROWNUMBER"
FROM ticket_table ticket
WHERE ( ticket.type = N'I' )
AND
(
ticket.tenant IS NULL OR ticket.tenant IN
(
SELECT * FROM
(
SELECT tenant_group_member.tenant_id
FROM tenant_group_member
WHERE tenant_group_member.tenant_group = HEXTORAW('30B0716FEB5F4E4BB82A7B7AA3A1A42C')
ORDER BY ticket.id
)
)
)
) DAL_ROWNOTABLE
WHERE DAL_ROWNOTABLE.DAL_ROWNUMBER BETWEEN 1 AND 21
What is the problem with the allow query that is throwing ORA-00936 missing expression? anyone? Any help will be appreciated...Error thrown at column:80 which is at the beginning of first order by:
ORA-00936 usually indicates a syntax error.
ROWNUMBER is not an Oracle function. Unless you have a user-defined function of that name I suspect the function you're looking for is ROW_NUMBER().
Your query can be much simplified. It has things like extra layers of subqueries and an unnecessary order by in an in subquery. What you want to do with rownumber you can do with just rownum:
SELECT DAL_ROWNOTABLE.DAL_ID
FROM (SELECT ticket.id AS "DAL_ID"
FROM ticket_table ticket
WHERE (ticket.type = N'I' ) AND
(ticket.tenant IS NULL OR
ticket.tenant IN (SELECT tgm.tenant_id
FROM tenant_group_member tgm
WHERE tgm.tenant_group = HEXTORAW('30B0716FEB5F4E4BB82A7B7AA3A1A42C')
)
)
ORDER BY ticket.id
) DAL_ROWNOTABLE
WHERE rownum <= 21;

Sql Server select and update X rows

I'm using Sql Server 2012.
I need to select rows from a table for processing. The number of rows needs to be variable. I need to update the rows I'm selecting to a "being processed" status - I have a guid to populate for this purpose.
I've encountered several examples of using row_number() and a couple of examples of ways of using CTE's, but I'm not sure on how to combine them (or if that's even the correct strategy). I would appreciate any insight.
Here is what I have so far:
DECLARE #SessionGuid uniqueidentifier, #rowcount bigint
SELECT #rowcount = 1000
SELECT #sessionguid = newid()
DECLARE #myProductChanges table (
ProductChangeId bigint
, ProductTypeId smallint
, SourceSystemId tinyint
, ChangeTypeId tinyint );
WITH NextPage AS
(
SELECT
ProductChangeId, ServiceSessionGuid,
ROW_NUMBER() OVER (ORDER BY ProductChangeId) AS 'RowNum'
FROM dbo.ProductChange
WHERE 'RowNum' < #rowcount
)
UPDATE dbo.ProductChange
SET ServiceSessionGuid = #sessionguid, ProcessingStateId = 2, UpdatedDate = getdate()
OUTPUT
INSERTED.ProductChangeId,
INSERTED.ProductTypeId,
INSERTED.SourceSystemId,
INSERTED.ChangeTypeId
INTO #myProductChanges
FROM dbo.ProductChange as pc join NextPage on pc.ProductChangeId = NextPage.ProductChangeId
From here I will select from my temp table and return the data:
SELECT mpc.ProductChangeId
, pt.ProductName as ProductType
, ss.Name as SourceSystem
, ct.ChangeDescription as ChangeType
FROM #myProductChanges as mpc
join dbo.R_ProductType pt on mpc.ProductTypeId = pt.ProductTypeId
join dbo.R_SourceSystem ss on mpc.SourceSystemId = ss.SourceSystemId
join dbo.R_ChangeType ct on mpc.ChangeTypeId = ct.ChangeTypeId
ORDER BY ProductType asc
So far this doesn't work for me. I get an error when I try to run it:
Msg 8114, Level 16, State 5, Line 20
Error converting data type varchar to bigint.
I'm not clear on what I'm doing wrong - so - any help is appreciated.
Thanks!
BTW, here are some of the questions I've used as reference to try and solve this:
https://stackoverflow.com/questions/9777178
https://stackoverflow.com/questions/3319842
https://stackoverflow.com/questions/6402103
This subquery makes no sense:
SELECT
ProductChangeId, ServiceSessionGuid,
ROW_NUMBER() OVER (ORDER BY ProductChangeId) AS 'RowNum'
FROM dbo.ProductChange
WHERE 'RowNum' < #rowcount
You can't reference the alias RowNum at the same scope (and you are trying to compare a string, not an alias, anyway), because when the WHERE clause is parsed, the SELECT list hasn't been materialized yet. What you need is either another nest:
SELECT ProductChangeId, ServiceSessionGuid, RowNum
FROM (SELECT ProductChangeId, ServiceSessionGuid,
ROW_NUMBER() OVER (ORDER BY ProductChangeId) AS RowNum
FROM dbo.ProductChange
) AS x WHERE RowNum < #rowcount
Or:
SELECT TOP (#rowcount-1) ProductChangeId, ServiceSessionGuid,
ROW_NUMBER() OVER (ORDER BY ProductChangeId) AS RowNum
FROM dbo.ProductChange
ORDER BY ProductChangeId
Also please stop using 'alias' - when you need to delimit aliases (you don't in this case), use [square brackets].
I'm guessing, but I think you want <= rather than < if you want to affect #rowcount rows, not one less.
Another tip is that CTEs can be updated directly*, as shown here:
WITH NextPage AS
(
SELECT TOP(#rowcount) *
FROM dbo.ProductChange
)
UPDATE NextPage
SET ServiceSessionGuid = #sessionguid, ProcessingStateId = 2, UpdatedDate = getdate()
OUTPUT
INSERTED.ProductChangeId,
INSERTED.ProductTypeId,
INSERTED.SourceSystemId,
INSERTED.ChangeTypeId
INTO #myProductChanges
* The updates affect the base table in the CTE, i.e. dbo.ProductChange