A view that shows the name of the server, the id of the instance and the number of active sessions (a session is active if the end timestamp is null) - postgresql

CREATE TABLE instances(
ser_name VARCHAR(20) NOT NULL,
id INTEGER NOT NULL ,
ser_ip VARCHAR(16) NOT NULL,
status VARCHAR(10) NOT NULL,
creation_ts TIMESTAMP,
CONSTRAINT instance_id PRIMARY KEY(id)
);
CREATE TABLE characters(
nickname VARCHAR(15) NOT NULL,
type VARCHAR(10) NOT NULL,
c_level INTEGER NOT NULL,
game_data VARCHAR(40) NOT NULL,
start_ts TIMESTAMP ,
end_ts TIMESTAMP NULL ,
player_ip VARCHAR(16) NOT NULL,
instance_id INTEGER NOT NULL,
player_username VARCHAR(15),
CONSTRAINT chara_nick PRIMARY KEY(nickname)
);
ALTER TABLE
instances ADD CONSTRAINT ins_ser_name FOREIGN KEY(ser_name) REFERENCES servers(name);
ALTER TABLE
instances ADD CONSTRAINT ins_ser_ip FOREIGN KEY(ser_ip) REFERENCES servers(ip);
ALTER TABLE
characters ADD CONSTRAINT chara_inst_id FOREIGN KEY(instance_id) REFERENCES instances(id);
ALTER TABLE
characters ADD CONSTRAINT chara_player_username FOREIGN KEY(player_username) REFERENCES players(username);
insert into instances values
('serverA','1','138.201.233.18','active','2020-10-20'),
('serverB','2','138.201.233.19','active','2020-10-20'),
('serverE','3','138.201.233.14','active','2020-10-20');
insert into characters values
('characterA','typeA','1','Game data of characterA','2020-07-18 02:12:12','2020-07-18 02:32:30','192.188.11.1','1','nabin123'),
('characterB','typeB','3','Game data of characterB','2020-07-19 02:10:12',null,'192.180.12.1','2','rabin123'),
('characterC','typeC','1','Game data of characterC','2020-07-18 02:12:12',null,'192.189.10.1','3','sabin123'),
('characterD','typeA','1','Game data of characterD','2020-07-18 02:12:12','2020-07-18 02:32:30','192.178.11.1','2','nabin123'),
('characterE','typeB','3','Game data of characterE','2020-07-19 02:10:12',null,'192.190.12.1','1','rabin123'),
('characterF','typeC','1','Game data of characterF','2020-07-18 02:12:12',null,'192.188.10.1','3','sabin123'),
('characterG','typeD','1','Game data of characterG','2020-07-18 02:12:12',null,'192.188.13.1','1','nabin123'),
('characterH','typeD','3','Game data of characterH','2020-07-19 02:10:12',null,'192.180.17.1','2','bipin123'),
('characterI','typeD','1','Game data of characterI','2020-07-18 02:12:12','2020-07-18 02:32:30','192.189.18.1','3','dhiraj123'),
('characterJ','typeD','3','Game data of characterJ','2020-07-18 02:12:12',null,'192.178.19.1','2','prabin123'),
('characterK','typeB','4','Game data of characterK','2020-07-19 02:10:12','2020-07-19 02:11:30','192.190.20.1','1','rabin123'),
('characterL','typeC','2','Game data of characterL','2020-07-18 02:12:12',null,'192.192.11.1','3','sabin123'),
('characterM','typeC','3','Game data of characterM','2020-07-18 02:12:12',null,'192.192.11.1','2','sabin123');
here I need a view that shows the name of the server, the id of the instance and the number of active sessions (a session is active if the end timestamp is null). do my code wrong or something else? i am starting to learn so hoping for positive best answers.
my view
create view active_sessions as
select i.ser_name, i.id, count(end_ts) as active
from instances i, characters c
where i.id=c.instance_id and c.end_ts = null
group by i.ser_name, i.id;

This does not do what you want:
where i.id = c.instance_id and c.end_ts = null
Nothing is equal to null. You need is null to check a value against null.
Also, count(end_ts) will always produce 0, as we know already that end_ts is null, which count() does not consider.
Finally, I would highly recommend using a standard join (with the on keyword), rather than an implicit join (with a comma in the from clause): this old syntax from decades ago should not be used in new code. I think that a left join is closer to what you want (it would also take in account instances that have no character at all).
So:
create view active_sessions as
select i.ser_name, i.id, count(c.nickname) as active
from instances i
left join characters c on i.id = c.instance_id and c.end_ts is null
group by i.ser_name, i.id;

Related

Modify existing query

I have two tables
create table jobs (
id varchar unique primary key,
account_email varchar not null,
active boolean not null default true,
enabled boolean not null default false,
name varchar (50) not null,
...
);
create table job_tags (
job_id varchar not null,
tag varchar(50) not null,
foreign key (job_id) references jobs(id) on delete cascade,
unique (job_id, tag)
);
And this sql query to get job SELECT * FROM jobs INNER JOIN job_categories ON (jobs.category_id=job_categories.category_id) WHERE jobs.id=$1
Since I have little experience I perform one more query in order to load job_tags. Is it possible to create only one? I work with golang sqlx, thanks
Yes, you almost got it:
SELECT * FROM jobs
INNER JOIN job_categories ON (jobs.category_id=job_categories.category_id)
INNER JOIN job_tags ON (jobs.id = job_tags.job_id)
WHERE jobs.id=$1

How to select last value insert in column ( like function LAST() for OracleDB)

I'm actually sutend and I'm setting up DB PostgreSQL for my AirsoftShop and some request on it. I need to find similar function as SELECT LAST(xx) FROM yy usable on SQL server and OracleDB i think. For return the last insert values in the column target by LAST().
I have this table :
CREATE TABLE munition.suivi_ammo (
type_ammo integer NOT NULL,
calibre integer NOT NULL,
event integer NOT NULL,
date_event date NOT NULL,
entrance integer NOT NULL,
exit integer NOT NULL,
inventory integer NOT NULL,
FOREIGN KEY (calibre) REFERENCES munition.index(numero),
FOREIGN KEY (event) REFERENCES munition.index(numero),
FOREIGN KEY (type_ammo) REFERENCES munition.index(numero)
);
and index for definition by number id :
CREATE TABLE munition.index (
numero integer NOT NULL,
definition text NOT NULL,
PRIMARY KEY (numero)
);
I want to select the last inventory insert in the table and calculate the current inventory according to the inflow and outflow made after my inventory
It's works when i do this type of request with specific date to be sure to only have the last one inventory, but I do not want to have to do it
SELECT index.definition,
Sum(suivi_ammo.inventory) + Sum(suivi_ammo.entrance) - Sum(suivi_ammo.exit) AS Stock
FROM munition.suivi_ammo
INNER JOIN munition.index ON suivi_ammo.type_ammo = index.numero
WHERE date_event < '03/05/2019' AND date_event >= '2019-04-10'
GROUP BY index.definition;
I also tried to used last_value() window function but doesn't work.
Thx !

design of table with checked column or column with reference to primary key which is updatable

I faced a problem when creating/designing tables in DB2.
I have two tables, table users and table countries created as shown bellow
create table users
(
firstname varchar(20) not null,
lastname varchar(20) not null,
gender char(1) not null check (gender in ('M','F')),
birthdate date not null,
country char(3) not null,
)
create table testing.countries
(
name varchar(60) not null,
code2 char(2) not null,
code3 char(3) not null
)
I want to have in a column country in table users a 3-char code of a country of origin and during insertion of data to be checked if it is valid (or better to say if it exists) from the list of countries which are stored in table countries.
Because DB2 doesn't support a subquery/subselect in a check option (which would be the best for me) then it looks like a candidate for a foreign key on column country in users referencing to a primary key on column code3 in countries. But in case there will be update of 3-char code of any country, it will be impossible to update it in simple way.
I know that the update of this will not be so often and can be done manually by first inserting new data to countries, then updating values in users and then deleting the old values in countries but unfortunately there will be more similar tables where data will have to be checked during insertion against another table and data in referenced table will be updated quite often and then the manual update is uncomfortable. And of course I want the data in users to be updated in case the update in countries will be done.
What I want to ask is how to solve this. I thought about some before or instead of trigger but BEFORE cannot be used to change data in other tables and INSTEAD OF is expecting UNTYPED VIEW not the TABLE
SQL0159N The statement references an object that identifies an unexpected
object type. Object: "COUNTRIES". Object type: "TABLE". Expected object type:
"UNTYPED VIEW". LINE NUMBER=2. SQLSTATE=42809`
Can you please advise me?
Thanks in advance
try Something like this:
create table testing.users
(
firstname varchar(20) not null,
lastname varchar(20) not null,
gender char(1) not null check (gender in ('M','F')),
birthdate date not null,
country char(3) not null
)
create table testing.countries
(
name varchar(60) not null,
code2 char(2) not null,
code3 char(3) not null
)
ALTER TABLE testing.users ADD CONSTRAINT testing.PK_Users PRIMARY KEY
(firstname, lastname);
ALTER TABLE testing.countries ADD CONSTRAINT testing.PK_Countries PRIMARY KEY
(code3);
ALTER TABLE testing.users ADD CONSTRAINT testing.FK_Users_Countries FOREIGN KEY
(country)
REFERENCES testing.users
(code3)
ON DELETE CASCADE;

Average MySQL in new table

I have a database about weather that updates every second.
It contains temperature and wind speed.
This is my database:
CREATE TABLE `new_table`.`test` (
`id` INT(10) NOT NULL,
`date` DATETIME() NOT NULL,
`temperature` VARCHAR(25) NOT NULL,
`wind_speed` INT(10) NOT NULL,
`humidity` FLOAT NOT NULL,
PRIMARY KEY (`id`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_bin;
I need to find the average temperature every hour.
This is my code:
Select SELECT AVG( temperature ), date
FROM new_table
GROUP BY HOUR ( date )
My coding is working but the problem is that I want to move the value and date of the average to another table.
This is the table:
CREATE TABLE `new_table.`table1` (
`idsea_state` INT(10) NOT NULL,
`dateavg` DATETIME() NOT NULL,
`avg_temperature` VARCHAR(25) NOT NULL,
PRIMARY KEY (`idsea_state`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_bin;
Is it possible? Can you give me the coding?
In order to insert new rows into a database based on data you have obtained from another table, you can do this by setting up an INSERT query targeting the destination table, then run a sub-query which will pull the data from the source table and then the result set returned from the sub-query will be used to provide the VALUES used for the INSERT command
Here is the basic structure, note that the VALUES keyword is not used:
INSERT INTO `table1`
(`dateavg`, `avg_temperature`)
SELECT `date` , avg(`temperature`)
FROM `test`;
Its also important to note that the position of the columns returned by result set will be sequentially matched to its respective position in the INSERT fields of the outer query
e.g. if you had a query
INSERT INTO table1 (`foo`, `bar`, `baz`)
SELECT (`a`, `y`, `g`) FROM table2
a would be inserted into foo
y would go into bar
g would go into baz
due to their respective positions
I have made a working demo - http://www.sqlfiddle.com/#!9/ff740/4
I made the below changes to simplify the example and just demonstrate the concept involved.
Here is the DDL changes I made to your original code
CREATE TABLE `test` (
`id` INT(10) NOT NULL AUTO_INCREMENT,
`date` DATETIME NOT NULL,
`temperature` FLOAT NOT NULL,
`wind_speed` INT(10),
`humidity` FLOAT ,
PRIMARY KEY (`id`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_bin;
CREATE TABLE `table1` (
`idsea_state` INT(10) NOT NULL AUTO_INCREMENT,
`dateavg` VARCHAR(55),
`avg_temperature` VARCHAR(25),
PRIMARY KEY (`idsea_state`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_bin;
INSERT INTO `test`
(`date`, `temperature`) VALUES
('2013-05-03', 7.5),
('2013-06-12', 17.5),
('2013-10-12', 37.5);
INSERT INTO `table1`
(`dateavg`, `avg_temperature`)
SELECT `date` , avg(`temperature`)
FROM `test`;

T-SQL 'Cannot insert the value NULL' error with non-NULL values

I'm migrating a Simple Membership database to Identity 2.0. I'm copying a CreateDate datetime NULL column to a CreateDate datetime NOT NULL column. I've examined all the records in the Membership.CreateDate column in the data source table to verify that they contain valid DateTimes. This error is returned:
Cannot insert the value NULL into column 'CreateDate', table 'Settlement.dbo.AspNetUsers'; column does not allow nulls. INSERT fails.
The statement has been terminated.
I've also tried deleting all the records in Membership but one (its CreateDate column contains 2012-12-27 01:35:03.610). I get the same error.
I'm running the script in SSMS.
Migration script excerpts:
CREATE TABLE [dbo].[AspNetUsers] (
[Id] [nvarchar](60) NOT NULL,
[UserName] [nvarchar](15) NOT NULL,
[AcId] INT NOT NULL,
[LocId] INT NOT NULL,
[CreateDate] [datetime] NOT NULL,
[Email] [nvarchar](60),
[EmailConfirmed] [bit] Default ((0)) NOT NULL,
[PasswordHash] [nvarchar] (100),
[SecurityStamp] [nvarchar] (60),
[PhoneNumber] [nvarchar] (15),
[PhoneNumberConfirmed] [bit] Default ((0)) NOT NULL,
[TwoFactorEnabled] [bit] Default ((0)) NOT NULL,
[LockoutEndDateUtc] [datetime],
[LockoutEnabled] [bit] Default ((0)) NOT NULL,
[AccessFailedCount] [int] Default ((0)) NOT NULL,
CONSTRAINT [PK_dbo.AspNetUsers] PRIMARY KEY ([Id])
);
GO
INSERT INTO AspNetUsers(Id, UserName, AcId, LocId, PasswordHash, SecurityStamp, CreateDate )
SELECT UserProfile.UserId, UserProfile.UserName, UserProfile.BaId, UserProfile.OfcId,
webpages_Membership.Password, webpages_Membership.PasswordSalt, webpages_Membership.CreateDate
FROM UserProfile
LEFT OUTER JOIN webpages_Membership ON UserProfile.UserId = webpages_Membership.UserId
GO
If I change the AspNetUsers CreateDate column to NULL it successfully copies the datetimes from table to table so I know all the column names and types are correct.
(After doing this I ran
ALTER TABLE [dbo].[AspNetUsers] ALTER COLUMN [CreateDate] datetime NOT NULL
and got the same error)
This is happening with the Production copy of the database. I have a development copy of the database generated through the same EF code first code and it successfully copies the data into the CreateDate NOT NULL field.
I'm at wits end at this point. Why am I getting a Cannot insert the value NULL into column error when the source data is valid datetimes? Or why doesn't it recognize the CreateDate columns data as valid datetimes?
You have some users in the UserProfile that haven't corresponding users in the webpages_Membership, so you try to insert users without any information. You must use INNER JOIN instead of LEFT OUTER JOIN or provide the default values for users which haven't corresponding information.