I am trying to create an indexed view using the following code (so that I can publish it to replication it as a table):
CREATE VIEW lc.vw_dates
WITH SCHEMABINDING
AS
SELECT DATEADD(day, DATEDIFF(day, 0, GETDATE()), number) AS SettingDate
FROM lc.numbers
WHERE number<8
GO
CREATE UNIQUE CLUSTERED INDEX
idx_LCDates ON lc.vw_dates(SettingDate)
lc.numbers is simply a table with 1 column (number) which is incremented by row 1-100.
However, I keep getting the error:
Column 'SettingDate' in view 'lc.vw_dates' cannot be used in an index or statistics or as a partition key because it is non-deterministic.
I realize that GETDATE() is non-deterministic. But, is there a way to make this work?
I am using MS SQL 2012.
Edit: The hope was to be able to Convert GetDate() to make it deterministic (it seems like it should be when stripping off the time). If nobody knows of a method to do this, I will close this question and mark the suggestion to create a calendar table as correct.
The definition of a deterministic function (from MSDN) is:
Deterministic functions always return the same result any time they are called with a specific set of input values and given the same state of the database. Nondeterministic functions may return different results each time they are called with a specific set of input values even if the database state that they access remains the same.
Note that this definition does not involve any particular span of time over which the result must remain the same. It must be the same result always, for a given input.
Any function you can imagine that always returns the date at the point the function is called, will by definition, return a different result if you run it one day and then again the next day (regardless of the state of the database).
Therefore, it is impossible for a function that returns the current date to be deterministic.
The only possible interpretation of this question that could enable a deterministic function, is if you were happy to pass as input to the function some information about what day it is.
Something like:
select fn_myDeterministicGetDate('2015-11-25')
But I think that would defeat the point as far as you're concerned.
Related
I need help on a basic calculation that I'm unable to figure on Tableau.
I am trying to setup a calculated field that has dependency on its previous value to calculate its current value. Here is a simple example from Excel -
Sample Exhibit
As you can see, each value in a row is dependent on its previous value and multiplied by a constant.
In Tableau, when I'm trying to create a calculated field, it is not letting me refer to itself (-1 lagged value) in the code. I'd appreciate any help on how this can be resolved. Thanks in advance!
Tableau can do this client side with a table calc. You’ll have to learn how table calcs operate from the help- especially partitioning and addressing. Then you can use the function Previous_Value() to refer to the previous value. Practice on something simple first to make sure you understand how previous value() works. Hint, the argument to that function doesn’t mean what most people assume it means
If you want to perform this calculation server side instead, then you’ll need to use custom SQL so you can specify an analytic aka windowing query
Check the LOOKUP field to get the value from the preceding row. For example: LOOKUP(SUM([Value]),-1)
https://help.tableau.com/current/pro/desktop/en-us/functions_functions_tablecalculation.htm#lookupexpression-offset
You may need to make yourself familiar with the Table Calculation partitioning if not getting the expected result.
I can do this using multiple commands in C# for the app I'm creating, but prefer a stored proc to eliminate issues with latency/locks, etc. (hopefully):
I have a table of 10 extensions (important fields):
SortOrder, Extension, IsUsed
First record will be set to IsUsed = true
When calling the stored proc, I need the IsUsed of the NEXT record in sort order to be set to true,the current record that is true set to false. When I hit the last record, rotate back to the first record.
Use Case: I need to rotate through a bank of usable numbers. Multiple people use the app, so cannot reuse. a number within the last 4 minutes (Bank of 10 will suffice, but we can extend if necessary). When the user requests a number, they get the next avail. I can build the table however needed, so any and all options to achieve use case are welcome.
I need to set the flag to true on the 1st record when stored proc is called. All other records should be false.
I have seen this, which is of interest, but doesn't quite answer:
Get "next" row from SQL Server database and flag it in single transaction
If all that you're using this for is to return a number to identify a session, I'd suggest scrapping the whole table idea and letting SQL Server do the work for you.
You can create a SEQUENCE object that will cycle and return the next value for you, without needing to write any code or maintain any tables.
CREATE SEQUENCE dbo.Extension
AS integer
START WITH 5
INCREMENT BY 5
MINVALUE 5
MAXVALUE 50
CYCLE;
This will return the number 5 the first time it's called, up to the number 50 on call number 10, and then start back over. You can adjust the numbers in the code to more or less do whatever you would like, though.
Get the next value like this:
SELECT NEXT VALUE FOR dbo.Extension;
And when/if you need to extend the range:
ALTER SEQUENCE dbo.Extension
MAXVALUE 100;
Play around with the idea on the Rextester demo.
Edit: In light of the comments above and below, I'd still stick with a SEQUENCE, I think.
Every time your code calls the table for an extension, use a query along the lines of this:
SELECT
Extension
FROM
ExtTable
WHERE
SortOrder = NEXT VALUE FOR dbo.Extension;
Functionally, this should do what you're after, again with no code to write or maintain.
This may be an easily solvable question but I can't see an immediate solution. I am calling a PostgreSQL function which returns multiple columns, 2 of which are relevant to this question - a date column & a numeric field of return values. An example of the function call would be
SELECT curr_date, return_val
FROM schema.function_name($1,$2);
With example output such as
"2014-07-31";0.003767
"2014-08-07";-0.028531
"2014-08-14";0.020051
"2014-08-21";-0.003541
"2014-08-28";0.007766
"2014-09-04";-0.021926
"2014-09-11";0.026330
"2014-09-18";0.008137
"2014-09-25";-0.033303
"2014-10-02";0.030100
"2014-10-09";-0.012116
"2014-10-16";-0.017148
So on, so forth. The data will always return from this function with the dates ascending. What I would like to do is to use Postgres's stddev_samp function on every row, but only considering the return_value's from that row's date back in time. Something like:
SELECT curr_date, return_val,
--stddev_samp(return_val) where curr_date <= curr_date of current row
FROM schema.function_name($1,$2);
Naturally, if I calculated the sample deviation of the return_value's from 2014-07-31 to 2014-10-02 in the sample provided, it would differ slightly to calculating it using the result set from 2014-07-31 to any other date present. I know I could probably write another function which takes a numeric array as input and returns the standard deviation as output, and then call this in my query above, but I'm hoping someone may have a simpler approach which I'm just currently not seeing. If any other information is required, feel free to ask. I'm using version 10.7.
demo:db<>fiddle
Using window functions:
SELECT
stddev_samp(return_val) OVER(ORDER BY curr_date)
FROM
mytable
My end goal is to have a box change color when the last 3 records input into a field (based on the time of input) in FileMaker achieve a certain criteria (ex. variance < 2). I would like to know how to make this happen, or how a calculation/script can be written to only look at the last 3 records.
There are several ways you could approach this. A simple one would be to use a script to:
Show all records in the given table;
Unsort them (assuming they were entered in chronological order; otherwise sort them by creation timestamp);
Omit all records except the last three;
Get the value of a summary field defined as Standard Deviation of your value field;
Set a global variable/field to the square of the returned value.
Then use the global variable/field to conditionally format your "box".
If you don't want to use a script, you will have to define a relationship in order to get the last three values in the table, regardless of the current found set and/or sort order. Or you may use the ExecuteSQL() function for this.
I will try to explain the problem on an abstract level first:
I have X amount of data as input, which is always going to have a field DATE. Before, the dates that came as input (after some process) where put in a table as output. Now, I am asked to put both the input dates and any date between the minimun date received and one year from that moment. If there was originally no input for some day between this two dates, all fields must come with 0, or equivalent.
Example. I have two inputs. One with '18/03/2017' and other with '18/03/2018'. I now need to create output data for all the missing dates between '18/03/2017' and '18/04/2017'. So, output '19/03/2017' with every field to 0, and the same for the 20th and 21st and so on.
I know to do this programmatically, but on powercenter I do not. I've been told to do the following (which I have done, but I would like to know of a better method):
Get the minimun date, day0. Then, with an aggregator, create 365 fields, each has that "day0"+1, day0+2, and so on, to create an artificial year.
After that we do several transformations like sorting the dates, union between them, to get the data ready for a joiner. The idea of the joiner is to do an Full Outer Join between the original data, and the data that is going to have all fields to 0 and that we got from the previous aggregator.
Then a router picks with one of its groups the data that had actual dates (and fields without nulls) and other group where all fields are null, and then said fields are given a 0 to finally be written to a table.
I am wondering how can this be achieved by, for starters, removing the need to add 365 days to a date. If I were to do this same process for 10 years intead of one, the task gets ridicolous really quick.
I was wondering about an XOR type of operation, or some other function that would cut the number of steps that need to be done for what I (maybe wrongly) feel is a simple task. Currently I now need 5 steps just to know which dates are missing between two dates, a minimun and one year from that point.
I have tried to be as clear as posible but if I failed at any point please let me know!
Im not sure what the aggregator is supposed to do?
The same with the 'full outer' join? A normal join on a constant port is fine :) c
Can you calculate the needed number of 'dublicates' before the 'joiner'? In that case a lookup configured to return 'all rows' and a less-than-or-equal predicate can help make the mapping much more readable.
In any case You will need a helper table (or file) with a sequence of numbers between 1 and the number of potential dublicates (or more)
I use our time-dimension in the warehouse, which have one row per day from 1753-01-01 and 200000 next days, and a primary integer column with values from 1 and up ...
You've identified you know how to do this programmatically and to be fair this problem is more suited to that sort of solution... but that doesn't exclude powercenter by any means, just feed the 2 dates into a java transformation, apply some code to produce all dates between them and for a record to be output for each. Java transformation is ideal for record generation
You've identified you know how to do this programmatically and to be fair this problem is more suited to that sort of solution... but that doesn't exclude powercenter by any means, just feed the 2 dates into a java transformation, apply some code to produce all dates between them and for a record to be output for each. Java transformation is ideal for record generation
Ok... so you could override your source qualifier to achieve this in the selection query itself (am giving Oracle based example as its what I'm used to and I'm assuming your data in is from a table). I looked up the connect syntax here
SQL to generate a list of numbers from 1 to 100
SELECT (MIN(tablea.DATEFIELD) + levquery.n - 1) AS Port1 FROM tablea, (SELECT LEVEL n FROM DUAL CONNECT BY LEVEL <= 365) as levquery
(Check if the query works for you - haven't access to pc to test it at the minute)