creating custom_id using the concatenation of three columns - sql

I have a table named Products having following columns:
create table Products
(ProductId int primary key identity(1,1),
GroupId int foreign key references ProductGroup(GroupId),
SubGroupId int foreign key references ProductSubGroup(SubGroupId),
Productcode as (GroupId + SubGroupId + ProductId),
ProductName nvarchar(50) not null unique,
ProductShortForm nvarchar(5) not null unique,
PiecesInCarton int not null,
WeightPerPiece decimal(4,2) not null,
PurchasePricePerCarton decimal(18,2) not null,
SalePricePerCarton_CatC decimal(18,2) not null,
SalePricePerCarton_CatB decimal(18,2) not null,
SalePricePerCarton_CatA decimal(18,2)
)
if GroupId = 34, SubGroupId = 22 and auto generated ProductId = 12
then ProductCode should be like 34-22-12
how do i do this?

Assuming you are using SQL Server, you would simply do:
Productcode as (concat(GroupId, '-', SubGroupId, '-', ProductId)),
The issue with your code is that + is interpreted as addition, rather than string concatenation.
In more recent versions, you can use concat_ws():
Productcode as (concat_ws('-', GroupId, SubGroupId, ProductId)),
CONCAT_WS allows you to specify a separator once to inject in between the instances that are being concatenated.
Also note that the inputs are implicitly converted to char types when you use CONCAT or CONCAT_WS so this syntax is simpler than other inline value concatenation methods.

I believe you are looking for a view from your table.
create view Products_View
as
select ProductId ,
GroupId,
SubGroupId,
Productcode as (GroupId + SubGroupId + ProductId) as ProductCode,
ProductName,
ProductShortForm,
PiecesInCarton,
WeightPerPiece,
PurchasePricePerCarton,
SalePricePerCarton_CatC,
SalePricePerCarton_CatB,
SalePricePerCarton_CatA
from products

Related

An aggregate may not appear in a computed column expression or check constraint. error while using MAX function

I am receiving
An aggregate may not appear in a computed column expression or check constraint error
while using MAX function for a date column to create a table. Here is the code I'm using to create the table:
Create table Bills
(
BillNo INT NOT NULL,
MeterNo INT NOT NULL,
FirstDate datetime NOT NULL,
FirstDateReading INT NOT NULL,
CurrentDate as MAX(FirstDate),
CurrentDateReadng INT NOT NULL,
LastDate as DATEADD(m,-1,CurrentDate),
LastDateReading INT NOT NULL,
Usageinm3 as (CurrentDateReadng-LastDateReading),
Usageinlitres as (Usageinm3 * 1000),
TotalBill as (UsageinLitres * 3)
Primary Key (BillNo),
Foreign Key (MeterNo) References MeterReading(MeterNo)
);
Since you are defining the table structure, you should put the data type for each column, not the value.
Create table Bills
(
BillNo INT NOT NULL,
MeterNo INT NOT NULL,
FirstDate datetime NOT NULL,
FirstDateReading INT NOT NULL,
CurrentDate as DATE, <--should be the data type
...
If you are creating a table based on other tables, you should use something like
SELECT billno,
meterno,
firstdate,
firstdatereading,
MAX(firstdate)
...
INTO Bills
FROM sourcetable
WHERE conditions
GROUP BY billno,
meterno,
firstdate,
firstdatereading
...

Can CAST and CONVERT be used in a table creation

I have never tried this sort of SQL query before, so excuse me for asking this question. Is it possible to use CAST and CONVERT in a table creation?
create table Owner
(
Id int identity(0,1)
, Name nvarchar(200)
, CountryId int
, PolicyNumber AS (CONVERT(CountryId AS char(3)) + CONVERT(Id AS char(10)) varchar(40)
)
go
Yes, it is called computed columns but you use it wrong:
create table Owner(
Id int identity(0,1)
,Name nvarchar(200)
,CountryId int
,PolicyNumber AS (CAST(CountryId AS VARCHAR(10)) + CAST(Id AS VARCHAR(10)))
)
go
LiveDemo
No need for final datatype so remove varchar(40)
CAST(col AS datatype) or CONVERT(datatype, col, style). Don't mix them.
If you use SQL Server 2012+ use simple CONCAT:
create table Owner(
Id int identity(0,1)
,Name nvarchar(200)
,CountryId int
,PolicyNumber AS (CONCAT(CountryId, Id)));
go
You should also:
add NOT NULL and PRIMARY KEY to Id
add REFERENCES to CountryId and make it NOT NULL also
add separator to computed column like - between both number(see demo)

How to store date and compare it in sql server?

basically, i need to make database for plants and their harvest dates.
For example, table with all the plants.
CREATE TABLE plant
(
plant_name NVARCHAR(20) NOT NULL
PRIMARY KEY ,
best_to_harvest_day INT NOT NULL ,
best_to_harvest_month NVARCHAR(15)
)
Example for plant entry: Rose 16 December
And another table called harvests
Where are multiple harvested plants and dates when they were harvested.
CREATE TABLE harvests
(
plant_name nvarchar(20) NOT NULL FOREIGN KEY REFERENCES plant(plant_name),
amount int NOT NULL,
havested_day int NOT NULL,
harvested_month nvarchar(15),
harvested year int NOT NULL
)
And this method does work, because i can make a sql query to compare which plants are harvested at their best time etc.
But isnt there a tidy way?
something like this: (using the date)
CREATE TABLE plant
(
plant_name NVARCHAR(20) NOT NULL
PRIMARY KEY ,
best_to_harvest DATE --But here should only be day and month, not year.
)
CREATE TABLE harvests
(
plant_name NVARCHAR(20) NOT NULL
FOREIGN KEY REFERENCES plant ( plant_name ) ,
amount INT NOT NULL ,
harvested DATE --But here i need full date year,day,month
)
Bottom line is that i need to compare them.
Okay, i think i can use EXTRACT(unit FROM date)
and then compare them but the question still stands, how to make plant table date not to consist of year?
First, store the date parts as numbers and check their values. This isn't perfect, but probably good enough:
CREATE TABLE plant (
plant_id int not null PRIMARY KEY,
plant_name nvarchar(20) NOT NULL UNIQUE,
best_to_harvest_day int NOT NULL,
best_to_harvest_month int not NULL,
check (best_to_harvest_day between 1 and 31),
check (best_to_harvest_month between 1 and 12)
);
Note the inclusion of an integer identity primary key. This is recommended, because integers are more efficient for foreign key references.
Then use date for the harvest:
CREATE TABLE harvests (
harvest_id int not null primary key,
plant_id int NOT NULL FOREIGN KEY REFERENCES plant(plant_id),
amount int NOT NULL,
harvested date --But here i need full date year,day,month
);
And you can do:
select h.*,
(case when p.best_to_harvest_day = day(h.harvest_day) and
p.best_to_harvest_month = month(h.harvest_month)
then 'Y' else 'N'
end)
from harvest h join
plant p
on h.plant_id = p.plant_id;

SQL Relation, one-to-many with a current used row

in sql i have a table of items. An item can have multiples prices. But when i come to using the data, most of the time i only need the currentPrice that i can find with the date.
My question : Would it be wrong to have 2 relation on price where and Item would have a relation with the currentPrice and all the price. Do there is a solution for this kind of problem to prevent complication in my mvc. Im currently using a viewModel with and the current price but if i could handle this in the database it seem better to me. (tell me if its not).
Note: I don't think this exact methode would work since I would need to create my price table before my item table and the same for the item table. But this show my problem.
Thanks alot for your help.
CREATE TABLE Item.Items
(
ItemId INT NOT NULL
CONSTRAINT PK_Items_ItemId
PRIMARY KEY
IDENTITY,
--------------------------------------------------
--CurrentPriceId INT NOT NULL
CONSTRAINT FK_Prices_Items
FOREIGN KEY REFERENCES Item.Items (ItemId),
--------------------------------------------------
Name VARCHAR(100) NOT NULL,
Points INT NOT NULL DEFAULT 0,
Description VARCHAR(5000) NULL
)
CREATE TABLE Item.Prices
(
PriceId INT NOT NULL
CONSTRAINT PK_ItemPrices_ItemPriceId
PRIMARY KEY
IDENTITY,
ItemId INT NOT NULL
CONSTRAINT FK_ItemPrices_Item
FOREIGN KEY REFERENCES Item.Items (ItemId),
EffectiveDate DATETIME NOT NULL,
Value MONEY NOT NULL
)
better would be:
CREATE TABLE Item.Items
(
ItemId INT NOT NULL
CONSTRAINT PK_Items_ItemId
PRIMARY KEY IDENTITY,
--------------------------------------------------
CurrentPrice MONEY NOT NULL, -- optional optimization, redundant as
-- current price is available from item.Prices
--------------------------------------------------
Name VARCHAR(100) NOT NULL,
Points INT NOT NULL DEFAULT 0,
Description VARCHAR(5000) NULL
)
CREATE TABLE Item.Prices
(
ItemId INT NOT NULL
CONSTRAINT FK_ItemPrices_Item
FOREIGN KEY REFERENCES Item.Items (ItemId),
EffectiveUtc DATETIME NOT NULL,
Price MONEY NOT NULL,
Constraint [ItemPricesPK] PRIMARY KEY CLUSTERED
(
[ItemId] ASC,
[EffectiveUtc] ASC
)
)
As mentioned by #popovitz, you can always get the price as of any specific date using a correlated subquery ...
Select i.name, p.price
From Item.Items i
Join Item.Prices p
ON i.ItemId = p.ItemId
Where p.EffectiveUtc =
(Select Max(EffectiveUtc )
From Item.Prices
Where ItemId = i.ItemId
And EffectiveUtc <= #asOfDate)
I would not recommend adding a currentPrice column, because you would have to constantly make sure that the item table is being updated whenever there a new price becomes effective. It's not that hard to query the current price when you have a table that contains the prices with an EffectiveDate column:
SELECT i.name, p.price FROM Items i
INNER JOIN Prices p ON i.ItemId = p.ItemId
WHERE p.EffectiveDate =
(SELECT MAX(EffectiveDate) FROM Price
WHERE EffectiveDate <= SYSDATE
AND ItemId = i.ItemId)
This will select the correct price for the current system time, assuming that (EffectiveDate, ItemId) is unique for the table prices.

Designing a rudimentary Shopping Cart database

create table [User]
(
UserId int primary key identity(1,1),
FirstName nvarchar(256) not null,
LastName nvarchar(256) not null,
)
create table Product
(
ProductId int primary key identity(1,1),
UnitPrice decimal(18,2) not null, //For catalog purposes.
Name nvarchar(1000) not null,
Description nvarchar(max) not null,
Stock int not null
)
create table [Order]
(
OrderId int primary key identity(1,1),
UserId int foreign key references [User](UserId),
ProductId int foreign key references Product(ProductId),
UnitCost decimal(18,2) not null, //How much it actually cost when the person bought it.
ItemCount int not null,
Subtotal decimal(18,2) not null
)
create table OrderDetail
(
OrderDetailId int primary key identity(1,1),
?
I'm stuck on the database design of the order system.
A user can choose n products to add to a order request. Any suggestions?
Following some advice given here, how would this feel? Any pitfalls?
create table [User]
(
UserId int primary key identity(1,1),
FirstName nvarchar(256) not null,
LastName nvarchar(256) not null,
)
create table Product
(
ProductId int primary key identity(1,1),
UnitPrice decimal(18,2) not null,
Name nvarchar(1000) not null,
Description nvarchar(max) not null,
Stock int not null
)
create table [Order]
(
OrderId int primary key identity(1,1),
UserId int foreign key references [User](UserId),
DateOfOrder datetime not null
)
create table OrderDetail
(
OrderDetailId int primary key identity(1,1),
OrderId int foreign key references [Order](OrderId),
ProductId int foreign key references Product(ProductId),
UnitCost decimal(18,2) not null,
ItemCount int not null,
Subtotal decimal(18,2) not null
)
Typically, you'd have the Order table with the top-level order information (who, when etc) and then an OrderItem (or OrderDetail) table which has a row for each product that forms part of the order including columns like:
OrderId
ProductId
Quantity
etc
Good candidate for a PK on this OrderItem/OrderDetail table would be on OrderId + ProductId.
So where you have columns like ProductId, UnitCost, ItemCount etc in the Order table, those are in the wrong place and should be in the OrderItem/OrderDetail table.
Update:
To set up a compound PK, you can do:
create table OrderDetail
(
OrderId int foreign key references [Order](OrderId),
ProductId int foreign key references Product(ProductId),
...other columns...,
CONSTRAINT PK_OrderDetail PRIMARY KEY(OrderId, ProductId)
)