Multiple inner joins in a query - sql

Players{
Pid int primary key,
tid int not null references Teams,
name text not null,
age int not null
}
Teams{
tid int primary key,
name text not null,
location not null
}
Possessions{
id int primary key,
pid int not null references Players,
time int not null, //the time the possession started for a player
held int not null //for how much time he had the ball
}
I would like to create a view called Teampasses where I can select (passer,passee) as follows:Passer and passe must be from the same team and passes possession starting time equals to passes possession starting time +held (time he has the ball). What I have done so far is this:
SELECT x.name AS passer,y.name as Pasee
FROM player x
INNER JOIN player y ON x.tid=y.tid
INNER JOIN possesions p ON p.pid=x.pid AND p.pid=y.pid AND ...
in the ... section right of AND i would like to do something like x.time+x.held=y.time.How could i refer to there two?

I see an issue with your data:
Your Possessions table only has a single foreign key to the Players table for the passer. It needs to also include the Pid of the Passee. Otherwise, there's no way to filter out which player on the passer team is the Passee for a given Possession.
I would suggest changing the Possessions table as follows:
Possessions(
id int primary key,
pid_passer int not null references Players,
pid_passee int not null references Players,
time int not null, //the time the possession started for a player
held int not null //for how much time he had the ball
)
With this change, your data will work and the query becomes trivial.

Related

Stored procedure with multiple tables with foreign key

I am working on an event management project. In that project, I have a form in admin panel as add event which contains events name, category, sub-category, event admin etc and more. And in the database, I have different tables like event category, event sub-category.
And also I have a table that is cultural event which includes form fields and foreign key. I pass event catid, event sub-cat id.
On button click that cultural event is added.
I want to insert data in their tables and I want id that I gave in cultural event table.
On single click I want to insert this
How can I achieve this? Using a stored procedure?
CREATE TABLE EVENT_SCAT (ESUBCAT_ID INT NOT NULL PRIMARY KEY, ECAT_ID INT NOT NULL FOREIGN KEY REFERENCES EVENT_CAT(ECAT_ID), ESUBCAT_NAME VARCHAR(255) NOT NULL, )
create table EVENT_CAT (ECAT_ID INT NOT NULL IDENTITY PRIMARY KEY, ECAT_NAME VARCHAR(255)NOT NULL, EID INT NOT NULL FOREIGN KEY REFERENCES EVENTDETAILS(EID)
CREATE TABLE Cultural_E (c_ID INT NOT NULL IDENTITY PRIMARY KEY, cEVENT_NAME VARCHAR(255) NOT NULL, cE_SDATE DATE NOT NULL, cE_EDATE DATE NOT NULL, SE_RULES1 VARCHAR(MAX), SE_RULES2 VARCHAR(MAX), SE_RULES3 VARCHAR(MAX), cE_RULES4 VARCHAR(MAX), cE_EFEES INT, EID INT NOT NULL FOREIGN KEY REFERENCES EVENTDETAILS(EID), ECAT_ID INT NOT NULL FOREIGN KEY REFERENCES EVENT_CAT(ECAT_ID) )
and i have form in asp.net which includes all fields in single form but there are different tables with foreign keys. and i want id of ecat id and subcatid in last table i.e Cultural_e.
for ex:THESE ARE TABLE
eVENT_T
ID ENAME EADMIN
1 CULTURAL NIKHIL
E_CAT
ID ECAT_NAME E_iD
1 SINGING 1
event_scat
ID eCAT_iD ESUBCAT_NAME
1 1 SOLO
NOW I HAVE TABLE THAT IS CULTURAL_T
THESE TABLE HAVE ITS OWN FILEDS AS WELL AS FOREIGN KEY LIKE EID ,ECAT_ID AS YOU CAN SEE ABOVE
AND I HAVE FORM IN ASP.NET AND FORM CONTAINS TEXTBOX TO ENTER DATA OF ALL THESE TABLE.
SO PLZ TELL ME HOW TO ACHIEVE THIS
THANK YOU
As per my understanding of your question,try to use triggers rather than stored procedures if possible.
CREATE TRIGGER InsertEvents
AFTER INSERT ON EVENT_CAT
BEGIN
/* Insert Query to EVENT_SCAT */
/* Insert Query to cultural */
END

What is wrong with my PSQL view table?

I have two tables player and match:
CREATE TABLE player(
id serial PRIMARY KEY NOT NULL,
name varchar(255) NOT NULL
);
CREATE TABLE match(
id serial PRIMARY KEY,
winner serial REFERENCES player(id) NOT NULL,
loser serial REFERENCES player(id) NOT NULL CHECK (loser != winner)
);
CREATE SEQUENCE playerid_sequence
start 1
increment 1;
CREATE SEQUENCE matchid_sequence
start 1
increment 1;
I want to create a view table that joins the two tables:
CREATE VIEW matchplayers AS
SELECT winner.name, loser.name, m.id
from player winner, player loser, match m
WHERE m.winner = winner.id AND m.loser = loser.id;
But it is returning an error that "name" has been mentioned more than once. Fairly inexperienced to SQL
Try
CREATE VIEW matchplayers AS
SELECT winner.name as winner_name, loser.name as loser_name, m.id
from player winner, player loser, match m
WHERE m.winner = winner.id AND m.loser = loser.id;
to get unambiguous column names of the view.

Reorder denormalized column values

I have a denormalized table that contains up to 8 user photos:
CREATE TABLE [dbo].[Users] (
Id int NOT NULL,
ProfileId int NOT NULL,
Photo1 int DEFAULT NULL,
Photo2 int DEFAULT NULL,
Photo3 int DEFAULT NULL,
Photo4 int DEFAULT NULL,
Photo5 int DEFAULT NULL,
Photo6 int DEFAULT NULL,
Photo7 int DEFAULT NULL,
Photo8 int DEFAULT NULL,
CONSTRAINT [PK_Users_ProfileId_Id] PRIMARY KEY CLUSTERED ([ProfileId], [Id])
)
A user can change the position of each photo (move it). What I would like to achieve is that when user moves a photo to another position, this photo must be saved to a different Photo-column and the rest of photos must be reordered:
If I move Photo8 to Photo1, it should save Photo8 to Photo1, Photo1 to Photo2, Photo2 to Photo3 ...
And if I move Photo2 to Photo4, it should save Photo2 to Photo4, Photo3 to Photo2, Photo4 to Photo3.
How can I achieve this with SQL and preferably without dynamic-generated SQL (EXEC-Method).
You should consider changing your DB design. For instance:
users table
-----------
id int
profile_id int
name varchar
....
photos table
------------
id int
user_id int
rank int
Then a user can have as many photos as he/she likes and you only need to change the rank to change the order of the photos.
This would then set photo 8 to 1 and the others will be reordered:
update photos
set rank = case when rank = 8 then 1
when rank between 1 and 7 then rank + 1
else rank
end
where user_id = 1
A thunb rule for DB design is when you need numbers in your column names (like photo1, photo2) then it is bad.
I'm assuming you do not want to change the DB. Consider solving this in the application code like this:
Copy the PhotoIDs to a List (with up to 8 items obviously)
Insert/delete/reorder as you like (this is easy in most languages)
Copy the list contents back to the columns
Steps 1 and 3 are reusable so you only need to write them once.

Beginner with triggers

Im a beginner in database and i got this difficult auction database project.
Im using SQL Server Management Studio also.
create table user(
name char(10) not null,
lastname char(10) not null
)
create table item(
buyer varchar(10) null,
seller varchar(10) not null,
startprice numeric(5) not null,
description char(22) not null,
start_date datetime not null,
end_date datetime not null,
seller char(10) not null,
item_nummer numeric(9) not null,
constraint fk_user foreign key (buyer) references user (name)
)
Basically what the rule im trying to make here is:
Column buyer has NULL unless the time (start_date and end_date) is over and startprice didnt go up or increased. Then column buyer will get the name from table user who bidded on the item.
The rule is a bid too difficult for me to make, i was thinking to make a trigger, but im not sure..
Your model is incorrect. First you need a table to store the bids. Then when the auction is over, you update the highest one as the winning bid. Proably the best way is to have a job that runs once a minute and finds the winners of any newly closed auctions.
A trigger will not work on the two tables you have because triggers only fire on insert/update or delete. It would not fire because the time is past. Further triggers are an advanced technique and a db beginner should avoid them as you can do horrendous damage with a badly written trigger.
You could have a trigger that works on insert to the bids table, that updates the bid to be the winner and takes that status away from the previous winner. Then you simply stop accepting new bids at the time the auction is over. Your application could show the bidder who is marked as the winner as the elader if the auction is till open and teh winner if it is closed.
There are some initial problems with your schema that need addressed before tackling your question. Here are changes I would make to significantly ease the implementation of the answer:
-- Added brackets around User b/c "user" is a reserved keyword
-- Added INT Identity PK to [User]
CREATE TABLE [user]
(
UserId INT NOT NULL
IDENTITY
PRIMARY KEY
, name CHAR(10) NOT NULL
, lastname CHAR(10) NOT NULL
)
/* changed item_nummer (I'm not sure what a nummer is...) to ItemId int not null identity primary key
Removed duplicate Seller columns and buyer column
Replaced buyer/seller columns with FK references to [User].UserId
Add currentBid to capture current bid
Added CurrentHighBidderId
Added WinningBidderId as computed column
*/
CREATE TABLE item
(
ItemId INT NOT NULL
IDENTITY
PRIMARY KEY
, SellerId INT NOT NULL
FOREIGN KEY REFERENCES [User] ( UserId )
, CurrentHighBidderId INT NULL
FOREIGN KEY REFERENCES [User] ( UserId )
, CurrentBid MONEY NOT NULL
, StartPrice NUMERIC(5) NOT NULL
, Description CHAR(22) NOT NULL
, StartDate DATETIME NOT NULL
, EndDate DATETIME NOT NULL
)
go
ALTER TABLE dbo.item ADD
WinningBidderId AS CASE WHEN EndDate < CURRENT_TIMESTAMP
AND currentBid > StartPrice THEN CurrentHighBidderId ELSE NULL END
GO
With the additional columns a computed column can return the correct information. If you must return the winner's name instead of id, then you could keep the schema above the same, add an additional column to store the user's name, populate it with a trigger and keep the computed column to conditionally show/not show the winner..

does it makes sense to use int instead of char or nvarchar for a discriminator column if I'm using it as FK also

I have something like this:
create table account
(
id int identity(1,1) primary key,
usertype char(1) check(usertype in ('a', 'b')) not null,
unique(id, usertype)
)
create table auser
(
id int primary key,
usertype char(1) check(usertype = 'a') not null,
foreign key (id, usertype) references account(id, usertype)
)
create table buser
(
... same just with b
)
the question is: if I'm going to use int instead of char(1), does it going to work faster/better ?
it doesn't matter on most modern databases. int is fine.
char as well.
(when the database fetch data from a table, it's not in byte size....)
why would you need IDENTITY columns: "auser.id" and "buser.id" that foreign key back to the "account.id" identity column?? seems hard to make sure everything could ever be in sync? When you insert into account you get an ID (say 1) and type "a", when you insert into "auser" you get an id (1) and FK to "account" how would you insert into "buser" (and get id 1) and fk back to account with 1,b??
Onto the real question. Size UserType to how many values you will have, if you will only have a few CHAR(1) is best, your index will take up less memory. if you will have more than a char(1) can hold, go tiny int (0-255, 1 byte), if you need more, go smallint (32k, 2 byte), if you need more go int (2,147,483,647, 4 byte)
A char(1) is 1 byte, whereas an int is 4 bytes. Even a small int is 2 bytes.