Does anyone know how I can make a generated column in Postgres?
This is the code in SQL Server:
CREATE TABLE [dbo].[PRICE]
(
[ISIN] [varchar](50) NOT NULL,
[Nemo] [varchar](50) NOT NULL,
[Month(t)] [int] NOT NULL,
[Month(t-1)] [int] NOT NULL,
[Month(t-2)] [int] NOT NULL
)
I searched the internet and found that the way to do it in Postgres is by using GENERATE ALWAYS AS but I get an error because the month column is repeated several times, that is the question that is supposed to be differentiated when doing the subtraction.
CREATE TABLE PRICE
(
ISIN varchar(50) NOT NULL,
Nemo varchar(50) NOT NULL,
Month int GENERATED ALWAYS AS (t) STORED,
Month int GENERATED ALWAYS AS (t-1) STORED,
Month int GENERATED ALWAYS AS (t-2) STORED,
)
postgres has a different syntax, You refer the column by name and create new columns.
Reference
CREATE TABLE PRICE(
ISIN varchar(50) NOT NULL,
Nemo varchar(50) NOT NULL,
Month int,
Month_1 int GENERATED ALWAYS AS (Month-1) STORED,
Month_2 int GENERATED ALWAYS AS (Month-2) STORED
);
Testing
insert into PRICE values('aaa','bbb',20)
select * from price;
isin
nemo
month
month_1
month_2
aaa
bbb
20
19
18
View on DB Fiddle
Those aren't generated columns, they just have non-standard names that need quoted identifiers. In SQL Server such a column needs to be enclosed in square brackets. Postgres follows the SQL standard where such names need to be enclosed in double quotes:
CREATE TABLE PRICE (
ISIN varchar(50) NOT NULL,
Nemo varchar(50) NOT NULL,
"Month(t)" int NOT NULL,
"Month(t-1)" int NOT NULL,
"Month(t-2)" int NOT NULL
)
Example with SQL Server
Example with PostgreSQL
Related
The schema is as follows:
create table Game
(
gameID int not null,
[name] varchar(30) not null,
developID int,
cost int not null,
category varchar(30) not null,
unique (gameID),
primary key(gameID),
);
create table Developer
(
developerID int not null,
[name] varchar(30) not null,
country varchar(30) not null,
speciality varchar(30) not null,
unique (developerID),
primary key (developerID)
);
Now, I want to find out the number of games developed by an American for each category. It must show 0 if no American has developed any game in that specific category
How would I write a nested SQL query for this requirement.
Thanks.
I believe this gets what you need. Unless there's some reason you need a nested query, this will work I think.
select count(*), category
from Game g
join Developer d on g.developID = d.developerID
where country = 'USA'
group by category
In nested query format, this should work, but it's less efficient than the joined version:
select count(*)
from Game g
where developID in (select developerid from Developer where country = 'USA')
I want to convert the following SQL server query into a Teradata BTEQ script. Could anyone help in this process..
The table creation logic is as follows and this needs to be converted to Teradata
CREATE TABLE [Eqp].[t_WSTCPEStairstep]
(
[SysID] [smallint] NULL,
[PrinID] [smallint] NULL,
[Account] [bigint] NOT NULL,
[Order_No] [bigint] NOT NULL,
[Order_Typ] [varchar] (1) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[Eqp_Serial] [varchar] (25) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[Eqp_Typ] [varchar] (2) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[Eqp_Model] [varchar] (9) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[Disco_Dte] [date] NULL,
[Return_Dte] [date] NULL,
[Restart_Dte] [date] NULL,
[Lost_Dte] [date] NULL,
[TestFlag] [smallint] NULL
) ON [PRIMARY]
WITH
(
DATA_COMPRESSION = PAGE
)
GO
CREATE NONCLUSTERED INDEX [ix_WSTCPEStairstepDiscoDteIndex] ON [Eqp].[t_WSTCPEStairstep] ([Disco_Dte]) ON [PRIMARY]
GO
CREATE CLUSTERED INDEX [ix_WSTCPEStairstepSPAIndex] ON [Eqp].[t_WSTCPEStairstep] ([SysID], [Account]) WITH (DATA_COMPRESSION = PAGE) ON [PRIMARY]
GO
I'm not sure about some of the SQL Server specific bits (compression, clustered, primary), but this will give you a start:
CREATE TABLE Eqp.t_WSTCPEStairstep (
SysID SMALLINT,
PrinID SMALLINT,
Account BIGINT NOT NULL,
Order_No BIGINT NOT NULL,
Order_Typ VARCHAR(1),
Eqp_Serial VARCHAR(25),
Eqp_Typ VARCHAR(2),
Eqp_Model VARCHAR(9) ,
Disco_Dte DATE,
Return_Dte DATE,
Restart_Dte DATE,
Lost_Dte DATE,
TestFlag SNALLINT
)
PRIMARY INDEX(col1, col2, ...);
-- Indexes
CREATE INDEX ix_WSTCPEStairstepDiscoDteIndex (Disco_Dte) ON Eqp.t_WSTCPEStairstep;
CREATE INDEX ix_WSTCPEStairstepSPAIndex (SysID, Account) ON Eqp.t_WSTCPEStairstep;
Which column(s) do you use to access data in this table? If they provide even distribution (i.e. mostly distinct values), then specify these as your PRIMARY INDEX fields. And if these fields are unique, better yet - UNIQUE PRIMARY INDEX. Maybe it's one of the indexes you specified -- disco_dte or (SysID, Account).
Some more notes:
columns should be NULLABLE by default
if TestFlag is just 1/0, you can use the BYTEINT data type
you may want to convert the VARCHAR(1) and VARCHAR(2) to CHAR
for compression, you can add that at multiple levels, but most common I think is at the column level
I have a simple SQL Server table of user loan applications.
CREATE TABLE [dbo].[Application]
(
[Id] INT NOT NULL,
[ApplicantId] INT NOT NULL,
[LoanAmount] INT NOT NULL,
[LoanTerm] SMALLINT NOT NULL,
[Accepted] BIT NOT NULL,
[BuyerId] SMALLINT NOT NULL,
[Commission] DECIMAL (9, 2) NOT NULL,
[PostTime] SMALLINT NOT NULL,
[CreatedOn] DATETIME NOT NULL,
PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [FK_Application_ToTable] FOREIGN KEY ([ApplicantId]) REFERENCES [dbo].[Applicant] ([Id])
);
I want to create a view over the table that provides two pieces of information. Firstly, the average time to process the application, and secondly, the percentage of applications that were accepted.
It's the second element I'm unsure about — I'm a complete SQL novice.
Here's what I have so far:
CREATE VIEW [dbo].[PostPerformance]
AS
SELECT AVG(PostTime) AS 'AvgPostTime'
FROM [Application]
As you can see AvgPostTime is simply enough but I'm unsure about how to calculate the percentage of loans that were accepted over a specific period.
Each row will have a 'true' or 'false' Accepted field — I'll need to count the number of entries that are true, and count the total rows in the selection, then calculate a percentage.
Any advice would be appreciated.
You have not provided sample data. I guess you are looking for this:
SELECT
AVG(PostTime) AS 'AvgPostTime'
, 100.0 * count(case when [Accepted] = 1 then 1 end) / count(*) AS [Percentage]
FROM [Application]
I have a SQL Server database with the following table:
CREATE TABLE [dbo].[Kanji] (
[KanjiId] UNIQUEIDENTIFIER DEFAULT (newid()) NOT NULL,
[Text] NVARCHAR (5) NOT NULL,
[Freq] INT NULL,
[Grade] INT NULL,
}
There are a large number of rows in this table and I would like to be able to select just 10%. Ideally I would like to have a column (maybe a computed column) in the table that was something like a hash value for the contents of the [Text] column. A hash that was a number from 0-9 so I could then select all rows that had this value.
Is there some way that I can create a column like this?
Try this:
CREATE TABLE [dbo].[Kanji] (
[KanjiId] UNIQUEIDENTIFIER DEFAULT (newid()) NOT NULL,
[Text] NVARCHAR (5) NOT NULL,
[Freq] INT NULL,
[Grade] INT NULL,
[Hash] AS (CONVERT([bigint],hashbytes('md5',[Name]))%(5)+(5)),
}
You'll get values from -9 to 9, for example.
I have the following two tables:
CREATE TABLE Portfolio.DailyPortfolio
(
BbgID varchar(30) NOT NULL,
Ticker varchar(22) NULL,
Cusip char(9) NULL,
SecurityDescription varchar(50) NOT NULL,
AssetCategory varchar(25) NOT NULL,
LSPosition char(3) NULL,
Ccy varchar(25) NOT NULL,
Quantity int NULL,
AvgCost decimal(7,3) NULL,
PriceLocal decimal(7,3) NULL,
Cost int NULL,
MktValNet int NULL,
GLPeriod int NULL,
Beta decimal(4,2) NULL,
BetaExpNet int NULL,
BetaExpGross int NULL,
Delta decimal(4,2) NULL,
DeltaExpNet int NULL,
DeltaExpGross int NULL,
Issuer varchar(48) NOT NULL,
Country varchar(30) NOT NULL,
Region varchar(20) NOT NULL,
Sector varchar(30) NOT NULL,
Industry varchar(48) NOT NULL,
MktCapCategory varchar(24) NULL,
MktCapEnd int NULL,
Date date NOT NULL,
PortfolioID AS BbgID+LSPosition+ Convert(varchar(8),Date,112) Persisted Primary Key
)
GO
Here is the second table:
CREATE TABLE Portfolio.DailyStats
(
Date date NOT NULL Primary Key,
NAV int NOT NULL,
SP500 decimal(8,4) NULL,
R2K decimal(8,4) NULL,
NetExp decimal(8,4) NULL,
GrossExp decimal(8,4) NULL,
)
GO
ALTER TABLE Portfolio.DailyStats
ADD [YrMn] as CONVERT(varchar(7), Date)
GO
Between 80-100 rows get added to the DailyPortfolio table every business day (the table has about 32,000 rows currently). 1 row gets added to the DailyStats table every business day (it has about 500 rows currently). The Date column in the Daily Portfolio table has a Foreign Key relationship with the Date column in the DailyStats table.
I had to create a view that included a few columns from both tables using last quarter as the date range. The last column of this view uses the Average of the NAV column in its calculation where the Average is calculated by using the NAV on the 1st date of each of the 3 months in the quarter. Here is my DDL for the view:
CREATE VIEW Portfolio.PNLLastQTD
AS
WITH CTE1
AS
(
Select Date, NAV,YrMn, ROW_NUMBER() OVER (PARTITION BY YrMn ORDER BY Date) AS Row
FROM Portfolio.DailyStats
WHERE DATE BETWEEN
(SELECT Convert(date, DATEADD(q, DATEDIFF(q,0,GETDATE()) -1 ,0)))
AND
(SELECT Convert(date, DATEADD(s,-1,DATEADD(q, DATEDIFF(q,0,GETDATE()),0))))
),
CTE2
AS
(
SELECT AvG (NAV) As AvgNAV
FROM CTE1
WHERE Row=1
)
SELECT IssuerLS, Issuer, Ticker, SUM (GLPeriod) As [PNL],
CAST(SUM(GLPeriod)As Decimal (13,2)) / CAST(CTE2.[AvgNAV] As Decimal (13,2)) as [%ofNAV]
FROM Portfolio.DailyPortfolioIssuerLS ls
JOIN cte2 on 1=1
WHERE ReportDate
BETWEEN
(SELECT Convert(date, DATEADD(q, DATEDIFF(q,0,GETDATE()) -1 ,0)))
AND
(SELECT Convert(date, DATEADD(s,-1,DATEADD(q, DATEDIFF(q,0,GETDATE()),0))))
GROUP BY
Issuer, Ticker, IssuerLS, CTE2.[AvgNAV]
GO
The view works fine but takes almost 20 seconds to execute! I have a couple of questions here:
Should there be some changes made to my DDL for the view?
Is it a good idea to create a non-clustered index on the date column (if at all possible) of the DailyPortfolio table?
Is there anything else I should be thinking of to improve query performance for this particular issue?
Thanks much for your help. Please forgive blatant mistakes as I'm new to SQL.
I wanted to close on the loop on this question. What I needed to do here was create two non clustered indices. I used the following steps:
Placed my query on the query window.
Clicked on "Display Estimated Execution Plan" button on my toolbox which immediately informed me of a missing non cluster index.
Created the first non-clustered index:
USE [OurDB]
GO
CREATE NONCLUSTERED INDEX NCI_DailyPort_Issuer_Date
ON [Portfolio].[DailyPortfolio] ([Issuer],[Date])
GO
Repeated step 2 and created the second non-clustered index as recommended:
USE [OurDB]
GO
CREATE NONCLUSTERED INDEX NCI_DailyPort_Date_INC_DexpN_Issuer
ON [Portfolio].[DailyPortfolio] ([Date])
INCLUDE ([DeltaExpNet],[Issuer])
GO
The query now takes less than 3 seconds to execute, significantly better than the 24 seconds it was taking before this.
Note: If you right click on the line that informs you about the missing index, you can choose an option to see the code for the index which saves you time.