I want to create a primary key in my select statement. I read that I can use ROW_NUMBER() over function. But as it is going to be primary key, i don't have any columns for over or partition by. I tried using just select row_number() as PKbut that throws error [3706] syntax error: expected something between ( and as keyword.
how could I resolve the issue?
You would need an over clause. I'm not sure if the order by is optional in Teradata (I don't have a version on hand):
row_number() over ()
row_number() over (order by <some column here>)
Are you trying to create a auto generated number which you can then use as a primary index for good distribution across the AMPs in Teradata nodes (which you refer to as PK in select statement) ?
If so, and if you dont want to use the IDENTITY COLUMN data type to do that for you (pros and cons exist), then you could generate such a auto number to be used as PI in Teardata by simply using a csum function. (Mind you, your target table must not be too large i.e. more than a few hundred thousands to a million)
SELECT
mx.max_id + csum(1,1) as PI_column
,src.columnABC
from
source_table src
cross join
(SELECT max(id) as max_id from target_table) as mx
group by 1,2
order by 1;
This will generate a new PI/PK/Unique ID column to be used for PI with good distribution for every unique combination of ColumnABC.
Hope this helps.
If my "if" statement at the beginning was not true, then please explain further what are you trying to do and i will be happy to help you with that.
Related
In MySQL there's some helpful syntax for doing things like SELECT #calc:=3,#calc, but I can't find the way to solve this on PostgreSQL
The idea would be something like:
SELECT (SET) autogen := UUID_GENERATE_v4() AS id, :autogen AS duplicated_id;
returning a row with 2 columns with same value
EDIT: Not interested in conventional \set, I need to do this for hundreds of rows
You can use a subquery:
select id, id as duplicated_id
from (select UUID_GENERATE_v4() AS id
) x
Postgres does not confuse the select statement by allowing variable assignment. Even if it did, nothing guarantees the order of evaluation of expressions in a select, so you still would not be sure that it worked.
I want to generate row numbers in the same order the data are added.
The below query is working fine for SQL Server.
SELECT *,ROW_NUMBER() OVER (ORDER BY (SELECT 100)) AS SNO FROM TestTable
I need standard query to achieve the same scenario in Firebird. Can anyone suggest me about this?
You can't use row_number() over (order by (select 100)) with Firebird, because Firebird - as required by the SQL standard - requires a from clause for a select. The equivalent in Firebird would be row_number() over (order by (select 100 from rdb$database)).
The best solution would be to use an actual column for the order by to ensure a deterministic order.
When looking at the SQL:2016 standard, then an order by is not required for row_number() (but it is for rank() and dense_rank()). Unfortunately, it looks like Microsoft applied that requirement for row_number() as well, possibly for uniformity with the rank-functions, and maybe because row_number() without an order does not make a lot of sense. Using row_number() over () with SQL Server yields an error "The function 'row_number' must have an OVER clause with ORDER BY.", but works with Firebird.
SQL Server also enforces that the order by in a window function is not a numeric column reference. Using row_number() over (order by 1) with SQL Server yields an error "Windowed functions, aggregates and NEXT VALUE FOR functions do not support integer indices as ORDER BY clause expressions.", but works with Firebird (although the 1 is taken as a literal 1, and not as column reference, contrary to an order by on select level).
SQL Server also does not support using constants or literals in the order by in a window function. Using row_number() over (order by '1') with SQL Server yields an error "Windowed functions, aggregates and NEXT VALUE FOR functions do not support constants as ORDER BY clause expressions.", but works with Firebird.
I did find a trick that worked for both Firebird 3 and SQL Server 2017, but it is a dirty hack:
row_number() over (order by current_user)
This works because SQL Server doesn't consider current_user as a constant, but as a function, which means it doesn't fall under the 'no constants allowed'-rule.
Be aware that this trick may yield inconsistent row numbers (eg in Firebird multiple window functions evaluated with different constants will yield different values, and the window function is evaluated before an order by on select level), and you may want to consider if you shouldn't simply track a row index in your application.
One way could be usage of ORDER BY RAND():
CREATE TABLE TestTable(i INT);
INSERT INTO TestTable(i) VALUES (10);
INSERT INTO TestTable(i) VALUES (20);
INSERT INTO TestTable(i) VALUES (30);
SELECT TestTable.*,ROW_NUMBER() OVER (ORDER BY RAND()) AS SNO
FROM TestTable;
db<>fiddle demo - Firebird
db<>fiddle demo - SQL Server
Is it possible to avoid specifying a column list in a SQL Server CTE?
I'd like to create a CTE from a table that has many columns so that the structure is identical. There probably is a way to accomplish this without relisting every column name.
I've tried (unsuccessfully):
with pay_cte as
(select * from payments)
select * from pay_cte
I'm encouraged in my quest by this statement in the msdn documentation:
The list of column names is optional only if distinct names for all resulting columns are supplied in the query definition.
https://msdn.microsoft.com/en-us/library/ms175972.aspx
Yes, assuming you mean that you don't have to name every column in the with cte(Col1, Col2) as section.
You can easily try this yourself with a very simple test query along the lines of:
with cte as
(
select *
from sys.tables
)
select *
from cte
I am new to PL SQL. I would like to fetch data on the basis of some unique attribute. May I use the UNIQUE keyword in WHERE clause? If yes then what would be the exact syntax.
Thanx in advance.
Syntax for using UNIQUE:
SELECT UNIQUE <column_name_list> FROM <table_name> WHERE <conditions>;
However, consider using the keyword DISTINCT for selecting unique values as UNIQUE is not standard across all SQL databases.
SELECT DISTINCT <column_name_list> FROM <table_name> WHERE <conditions>;
See this post for explanation.
To select only the unique values from a certain column, all you have to do is:
SELECT UNIQUE columnName FROM tableName;
Is it possible to use subqueries within alter expressions in PostgreSQL?
I want to alter a sequence value based on a primary key column value.
I tried using the following expression, but it wouldn't execute.
alter sequence public.sequenceX restart with (select max(table_id)+1 from table)
I don't believe you can do it like that but you should be able to use the setval function direction which is what the alter does.
select setval('sequenceX', (select max(table_id)+1 from table), false)
The false will make it return the next sequence number as exactly what is given.
In addition if you have mixed case object names and you're getting an error like this:
ERROR: relation "public.mytable_id_seq" does not exist
... the following version using regclass should be useful:
select setval('"public"."MyTable_Id_seq"'::regclass, (select MAX("Id") FROM "public"."MyTable"))