Updating a view using union clause in Snowflake - snowflake-cloud-data-platform

I have a view named viewA and another view named viewB. The goal is to update viewA by appending data from viewB. But the name of viewA should remain unchanged. And the other requirement is that viewB gets updated hourly. So viewA has to get updated at the same frequency.
Here is my attempt;
create or replace view viewA as(
SELECT *
FROM viewA
UNION ALL
SELECT *
FROM viewB;)
But this is giving me an Invalid create statement error. Can I please get some help on how to meet above requirements. thanks

I think what you need here is Recursive views as you want to create a view that refers to itself.

Related

column_list in views are displayed as manadory

In recent day, <column_list> is added automatically to views, eventhough the parameter is documented as optional: https://docs.snowflake.com/en/sql-reference/sql/create-view.html .
This causes views that are defined as
create view my_view
as
select *
from tbl
to throw an error, if a new field is added to a table, unless the view is refreshed.
Is there a way to define <column_list> as optional?
This behavior is by designand it is decribed at CREATE VIEW - Usage Notes:
View definitions are not dynamic. A view is not automatically updated if the underlying sources are modified such that they no longer match the view definition, particularly when columns are dropped
To reporduce the case:
CREATE OR REPLACE TABLE t AS SELECT 1 AS c;
CREATE VIEW v_t AS SELECT * FROM t;
SELECT * FROM v_t;
ALTER TABLE t ADD COLUMN d INT;
SELECT * FROM v_t;
-- SQL compilation error:
-- View definition for 'PUBLIC.V_T' declared 1 column(s),
-- but view query produces 2 column(s).

Return records for current and previous year with year passed in a WHERE clause for Acumatica report

Suppose I have a SQL view called INForecastTotalSales.
This view contains the following columns:
InventoryID, FinYear, TotalSales
I would like to create another view INForecastTotalSalePrevCurr, which would have the following columns:
InventoryID, FinYear, CurrentYearTotalSales, PreviousYearTotalSales
so that when I query
SELECT * FROM INForecastTotalSalePrevCurr i WHERE i.FinYear = 2020
the view would populate CurrentYearTotalSales, PreviousYearTotalSales with TotalSales data for 2020 and 2019 respectively. The catch if we have to join the original view on itself, it would have to be FULL OUTER JOIN, since we need data from both tables for all inventory id's.
I have tried using OUTER APPLY and putting the same view into a table valued function, but this would essentially work as LEFT JOIN.
The view would have to be used in Acumatica Report, so can't really pass parameters, if I were to use a function or stored procedure. I am limited to using WHERE clause, unless someone has some other suggestions.
Why do you need 2 views?
Better approach would be to create a single view with columns:
InventoryID, FinYear, CurrentYearTotalSales, PreviousYearTotalSales, TotalSales
Where I think you are going wrong is the assumption that you have to use SELCT * FROM .... In fact this a poor approach and it is bettwe to explicitly state the columns as in:
SELECT InventoryID, FinYear, TotalSales FROM INForecastTotalSales
or
SELECT InventoryID, FinYear, CurrentYearTotalSales, PreviousYearTotalSales FROM INForecastTotalSales
That will likely simplify your view creation and also make your queries more robust.

SQL Server: view or function contains a self-reference. Views or functions cannot reference themselves directly or indirectly

I'm trying to change the date format of a column stored in a view by doing an ALTER VIEW statement, but it's not working and I'm not sure why.
My query:
ALTER VIEW v_cust_invoices
AS
SELECT
FORMAT(INV_DATE,'MM-dd-yy') as INV_DATE
FROM
v_cust_invoices
I always get the error
View or function 'v_cust_invoices' contains a self-reference. Views or functions cannot reference themselves directly or indirectly
I'm trying to change the date format of INV_DATE to mm-dd-yy (it's currently yy-mm-dd). Can someone help me? Not sure what I'm doing wrong.
Edit: If I do
ALTER VIEW v_cust_invoices
AS
SELECT FORMAT(INV_DATE,'MM-dd-yy') as INV_DATE
FROM INVOICE
instead, it deletes all of the columns except for INV_DATE.
View definition:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE VIEW [dbo].[v_cust_invoices] AS
SELECT
CUSTOMER.CUST_NUM, CUST_LNAME,
CUST_BALANCE, INV_NUM, INV_DATE, INV_AMOUNT
FROM
CUSTOMER, INVOICE
GO
You must change the query so that it does not reference itself.
Look at the current definition of the v_cust_invoices view, at its FROM clause. You will see a reference to a table or to some other view. replace the last line in your query with the last line below, substituting the name of the table (or other view) this view gets it's data from.
ALTER VIEW v_cust_invoices
AS
SELECT FORMAT(INV_DATE,'MM-dd-yy') as INV_DATE,
[Plus all the rest of the output columns
from CURRENT definition of v_cust_invoices]
FROM [here Put the table or other view that is in current view definition]
or, now that op has posted complete view definition:
ALTER VIEW [dbo].[v_cust_invoices] AS
SELECT FORMAT(INV_DATE,'MM-dd-yy') INV_DATE,
CUSTOMER.CUST_NUM, CUST_LNAME,
CUST_BALANCE, INV_NUM, INV_DTE, INV_AMOUNT
FROM CUSTOMER, INVOICE
GO

Order BY is not supported in view in sql server

i am trying to create a view in sql server.
create view distinct_product as
select distinct name from stg_user_dtlprod_allignmnt_vw order by name;
this is showing an error.
error message is:
The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions, unless TOP or FOR XML is also specified.
plz help me out where i am wrong.
You could use TOP with a number that is greater than the number of records:
CREATE VIEW [dbo].[distinct_product]
AS
SELECT DISTINCT TOP 10000000 name
FROM stg_user_dtlprod_allignmnt_vw
ORDER BY name
You cannot use TOP 100 PERCENT since the optimizer recognizes that TOP 100 PERCENT qualifies all rows and does not need to be computed at all, so the ORDER BY wouldn't be guaranteed.
A view cannot be sorted with an ORDER BY clause. You need to put the ORDER BY clause into any query that references the view.
A view is not materialized - the data isn't stored, so how could it be sorted? A view is kind of like a stored procedure that just contains a SELECT with no parameters... it doesn't hold data, it just holds the definition of the query. Since different references to the view could need data sorted in different ways, the way that you do this - just like selecting from a table, which is also an unsorted collection of rows, by definition - is to include the order by on the outer query.
You can't order a view like that when it's created as the message states, unless you follow the other answers from Tim / Raphael, but you can order results selected from a view:
So create it in step 1:
create view distinct_product as
select distinct name
from stg_user_dtlprod_allignmnt_vw
Then order it when you retrieve data:
select *
from distinct_product
order by name

T-SQL: Alter View

I have a view with a field for date as a varchar. I need to change it to date time using the following code
CONVERT(DATETIME, MyDates)
This works fine when executing the view but I want to make the change permanent. I need some help with the syntax. So far I have
ALTER VIEW tableName
CONVERT(DATETIME, MyDates)
but it's obviously not working
Since a view (unless it's a materialized/indexed view which has some extra peculiarities) is more or less just a stored select query, what you do is to just change the select query and alter the view using that.
For example, if you have the view;
CREATE VIEW testview AS
SELECT id, value FROM test;
...where value is a varchar and you want it to be reflected in the view as a datetime, you can just issue;
ALTER VIEW testview AS
SELECT id, CAST(value AS DATETIME) value FROM test;
...to make it appear as a datetime in the view.
An SQLfiddle with a simple demo.
A view only fetches the data from the table as per the query.So you cannot change the datatype of the view. you have to change it in table.

Resources