whether i right join or left join i get the same output why and how to fix it? - mysql-workbench

CREATE TABLE teacher(
id INT PRIMARY KEY AUTO_INCREMENT, -- PRIMARY KEY AUTO_INCREMENt
name_ VARCHAR(45),
age INT,
class INT
);
CREATE TABLE student(
id INT PRIMARY KEY AUTO_INCREMENT ,
name_ VARCHAR(45),
class INT
);
INSERT INTO teacher(id, name_ , age, class) VALUES
(DEFAULT ,"Ali", 40, null),
(DEFAULT, "Reza", 30, 2),
(DEFAULT, "Yosef", 50, 3),
(DEFAULT, "Ibrahim", 60, 2);
INSERT INTO student(id, name_, class)VALUES
(DEFAULT, "Hasan", 2),
(DEFAULT, "Hosein", null),
(DEFAULT, "Hamed", 4),
(DEFAULT, "Idris", 1);
SELECT * FROM teacher
LEFT JOIN student
ON teacher.id = student.id ;
i dropped the tables and tried again and again,

Related

How to join multiple tables when creating a CTE Recursive Query

I am trying to create a recursive query that will take attributes from 3 different tables but I fail to JOIN the tables correctly and therefore I cannot select the desired attributes:
I have 3 tables:
tb_register
CREATE TABLE olympic.tb_register (
athlete_id CHARACTER(7) NOT NULL,
round_number INT NOT NULL,
discipline_id INT NOT NULL,
register_position INT DEFAULT NULL,
CONSTRAINT pk_register PRIMARY KEY (athlete_id, round_number, discipline_id),
CONSTRAINT fk_register_athlete FOREIGN KEY (athlete_id) REFERENCES olympic.tb_athlete (athlete_id),
CONSTRAINT fk_register_round FOREIGN KEY (discipline_id, round_number) REFERENCES olympic.tb_round (discipline_id, round_number)
);
athlete_id round_number discipline_id register_position
"1349038" 3 16 0
"1393212" 3 16 1
"1318621" 3 16 2
"1451030" 3 16 3
"1343607" 3 16 4
"1435826" 3 16 5
INSERT INTO olympic.tb_register(athlete_id, round_number, discipline_id, register_position) VALUES('1349038', 3, 16, 0);
INSERT INTO olympic.tb_register(athlete_id, round_number, discipline_id, register_position) VALUES('1393212', 3, 16, 1);
INSERT INTO olympic.tb_register(athlete_id, round_number, discipline_id, register_position) VALUES('1318621', 3, 16, 2);
INSERT INTO olympic.tb_register(athlete_id, round_number, discipline_id, register_position) VALUES('1451030', 3, 16, 3);
INSERT INTO olympic.tb_register(athlete_id, round_number, discipline_id, register_position) VALUES('1343607', 3, 16, 4);
INSERT INTO olympic.tb_register(athlete_id, round_number, discipline_id, register_position) VALUES('1435826', 3, 16, 5);
tb_athlete
CREATE TABLE olympic.tb_athlete (
athlete_id CHARACTER(7) NOT NULL,
name CHARACTER VARYING(50) NOT NULL,
country CHARACTER VARYING(3) NOT NULL,
substitute_id CHARACTER(7) DEFAULT NULL,
CONSTRAINT pk_athlete PRIMARY KEY (athlete_id),
CONSTRAINT fk_athlete_substitute FOREIGN KEY (substitute_id) REFERENCES olympic.tb_athlete (athlete_id)
);
athlete_id athlete_name country
"1349038" "AALERUD Katrine" "NOR"
"1393212" "ABASS Abobakr" "SUD"
"1451030" "ABDALLA Abubaker Haydar" "QAT"
"1444255" "ABDEL LATIF Radwa" "EGY"
INSERT INTO olympic.tb_athlete(athlete_id, name, country, substitute_id) VALUES('1346266','AALERUD Katrine','NOR',NULL);
INSERT INTO olympic.tb_athlete(athlete_id, name, country, substitute_id) VALUES('1344792','ABASS Abobakr','SUD',NULL);
INSERT INTO olympic.tb_athlete(athlete_id, name, country, substitute_id) VALUES('1328854','ABDALLA Abubaker Haydar','QAT',NULL);
INSERT INTO olympic.tb_athlete(athlete_id, name, country, substitute_id) VALUES('1306332','ABDEL LATIF Radwa','EGY',NULL);
tb_discipline
CREATE TABLE olympic.tb_discipline (
discipline_id INT NOT NULL,
name CHARACTER VARYING(50) NOT NULL,
inventor CHARACTER VARYING(50) NOT NULL,
type CHARACTER VARYING(10) NOT NULL,
object_type CHARACTER VARYING(20) DEFAULT NULL,
CONSTRAINT ck_discipline_type CHECK (type IN ('RUN', 'JUMP', 'THROW')),
CONSTRAINT pk_discipline PRIMARY KEY (discipline_id)
);
discipline_id discipline_name inventor type
16 "Triathlon" "Carina Melina" "RUN"
INSERT INTO olympic.tb_discipline(discipline_id, name, inventor, type, object_type) VALUES(16,'Triathlon','Carina Melina','RUN',null);
Desired output
I am trying to create a recursive query to obtain this result:
discipline_name, round_number, register_position, a_position
Triathlon, 3, 0, 0:AALERUD Katrine,
Triathlon, 3, 1, 0:AALERUD Katrine -> 1: ABASS Abobakr
Triathlon, 3, 2, 0:AALERUD Katrine -> 1: ABASS Abobakr -> ABDALLA Abubaker Haydar
where a_position is a list of athlete names with their respective position.
My code:
WITH RECURSIVE athlete_hierarchy AS (
SELECT
discipline_name,
round_number,
register_position,
CAST (athlete_name AS TEXT) AS a_position,
register_position AS first_athlete
FROM
olympic.tb_register
JOIN tb_discipline
ON discipline_id = tb_discipline.discipline_id
JOIN tb_athlete
ON athlete_id = tb_athlete.athlete_id;
WHERE
round_number IS 3
UNION ALL
SELECT
a.discipline_name,
a.round_number,
a.register_position,
CAST ( a.athlethe_name || ' -> ' || a2.a_position AS TEXT) AS a_position,
c2.first_athlete AS first_athlete
FROM
olympic.tb_register INNER JOIN athlete_hierarchy
ON (a.athlete_id = a2.athlete_id)
)
SELECT
discipline_name,
round_number,
register_position,
a_position,
first_athlete
FROM athlete_hierarchy;
Can anyone help me understand how to join 3 tables when creating a CTE Recursive Query?
Here is the solution :
WITH RECURSIVE athlete_hierarchy (discipline_id, discipline_name, round_number, register_position, a_position) AS
(SELECT
d.discipline_id,
d.name,
r.round_number,
r.register_position,
r.register_position || ':' || CAST (a.name AS TEXT)
FROM tb_register AS r
JOIN tb_discipline AS d
ON r.discipline_id = d.discipline_id
JOIN tb_athlete AS a
ON r.athlete_id = a.athlete_id
WHERE r.round_number = 3
AND r.register_position = 0
UNION ALL
SELECT
ah.discipline_id,
ah.discipline_name,
ah.round_number,
r.register_position,
ah.a_position || ' -> ' || r.register_position || ':' || CAST (a.name AS TEXT)
FROM tb_register AS r
INNER JOIN athlete_hierarchy AS ah
ON ah.discipline_id = r.discipline_id
AND ah.round_number = r.round_number
AND ah.register_position = r.register_position - 1
INNER JOIN tb_athlete AS a
ON r.athlete_id = a.athlete_id
)
SELECT discipline_name, round_number, register_position, a_position
FROM athlete_hierarchy
ORDER BY register_position
and the test result from your data sample is in db<>fiddle.

Cannot enter data into tables with inter related foreign keys

I have created the tables with following code, but the foreign key constraints does not allow data addition. What can I do to solve this problem?
CREATE TABLE Employee(
Ssn VARCHAR(10) PRIMARY KEY NOT NULL,
BDate DATE,
FName VARCHAR(25),
MInit VARCHAR(5),
LName VARCHAR(25),
Address VARCHAR(40),
Sex VARCHAR(6),
Salary INT,
SupervisorSsn VARCHAR(10),
DNumber INT
);
CREATE TABLE
CREATE TABLE Department(
DNumber INT PRIMARY KEY NOT NULL,
DName VARCHAR(15),
MgrSsn VARCHAR(10),
MgrStartDate DATE,
NumberofEmployees INT,
CONSTRAINT Department_MgrSsn_FK FOREIGN KEY(MgrSsn) REFERENCES Employee(Ssn) ON DELETE SET DEFAULT ON UPDATE CASCADE
);
ALTER TABLE Employee
ADD CONSTRAINT Employee_SupervisorSsn_FK FOREIGN KEY(SupervisorSsn) REFERENCES Employee(Ssn) ON DELETE SET DEFAULT ON UPDATE CASCADE,
ADD CONSTRAINT Employee_DNumber_FK FOREIGN KEY(DNumber) REFERENCES Department(DNumber) ON DELETE SET DEFAULT ON UPDATE CASCADE;
There are several ways to do that in Postgres.
Update later
The most obvious one: insert null values firs, then update it later:
insert into department
(dnumber, dname)
values
(1, 'One'),
(2, 'Two'),
(3, 'Three');
insert into employee (ssn, fname, lname, supervisorssn, dnumber)
values
('123', 'Arthur', 'Dent', '456', 1),
('456', 'Ford', 'Prefect', null, 2),
('789', 'Zaphod', 'Beeblebrox', null, 3);
update department
set mgrssn = '456'
where dnumber in (1,2);
update department
set mgrssn = '789'
where dnumber = 3;
Online example
Deferred constraints
Make the constraints deferred, so that they will be checked at the end of the transaction, rather when running the INSERT:
ALTER TABLE department
add constraint fk_dempt2emp foreign key (mgrssn) references employee
deferrable initially deferred; --<<
Then you can insert the rows in any order you like as long as everything happens in a single transaction:
begin transaction; --<< important!
insert into department
(dnumber, dname, mgrssn)
values
(1, 'One', '456'),
(2, 'Two', '456'),
(3, 'Three', '789')
insert into employee (ssn, fname, lname, supervisorssn, dnumber)
values
('123', 'Arthur', 'Dent', '456', 1),
('456', 'Ford', 'Prefect', null, 2),
('789', 'Zaphod', 'Beeblebrox', null, 3);
commit; -- the FKs will be checked here
Do everything in a single statement
You can use a data modifying CTE to insert rows into two tables. As this is evaluated as a single statement, the constraints do not need to be deferrable.
with new_depts as (
insert into department
(dnumber, dname, mgrssn)
values
(1, 'One', '456'),
(2, 'Two', '456'),
(3, 'Three', '789')
)
insert into employee (ssn, fname, lname, supervisorssn, dnumber)
values
('123', 'Arthur', 'Dent', '456', 1),
('456', 'Ford', 'Prefect', null, 2),
('789', 'Zaphod', 'Beeblebrox', null, 3)
;
Online example

Aggregation giving wrong result in T-SQL

I am getting wrong sum of values in more than two tables.
Please advise the correct qry for the below
my sample data is as follows.
IF OBJECT_ID('tempdb..#Departamentos') IS NOT NULL
DROP TABLE #Departamentos
GO
CREATE TABLE #Departamentos (ID INT IDENTITY(1,1) PRIMARY KEY,
Nome_Dep VARCHAR(200))
GO
INSERT INTO #Departamentos(Nome_Dep)
VALUES('Vendas'), ('TI'), ('Recursos Humanos')
GO
IF OBJECT_ID('tempdb..#Funcionarios') IS NOT NULL
DROP TABLE #Funcionarios
GO
CREATE TABLE #Funcionarios (ID INT IDENTITY(1,1) PRIMARY KEY,
ID_Dep INT,
Nome VARCHAR(200),
Salario Numeric(18,2))
GO
INSERT INTO #Funcionarios (ID_Dep, Nome, Salario)
VALUES(1, 'Fabiano', 2000), (1, 'Amorim', 2000), (1, 'Diego', 9000),
(2, 'Felipe', 2000), (2, 'Ferreira', 2500), (2, 'Nogare', 11999),
(3, 'Laerte', 5000), (3, 'Luciano', 23500), (3, 'Zavaschi', 13999)
GO
IF OBJECT_ID('tempdb..#deals') IS NOT NULL
DROP TABLE #deals
GO
CREATE TABLE #deals (ID INT IDENTITY(1,1) PRIMARY KEY,
ID_Deal INT,
Nome VARCHAR(200),
Revenue Numeric(18,2))
GO
INSERT INTO #deals (ID_Deal, Nome, Revenue)
VALUES(1, 'Fabiano', 50), (1, 'Amorim', 20), (1, 'Diego', 90),
(2, 'Felipe', 20), (2, 'Ferreira', 25), (2, 'Nogare', 119),
(3, 'Laerte', 50), (3, 'Luciano', 23), (3, 'Zavaschi', 13)
GO
My query is as follows to get the result:
select d.id,d.Nome_Dep,sum(salario)salario,sum(revenue)revenue from #Departamentos d left join #Funcionarios f on d.ID=f.ID_Dep
left join #deals dd on dd.ID_Deal=d.ID
group by d.id,d.Nome_Dep
But my desired result should be:
ID Nome_Dep salario revenue
1 Vendas 13000.00 160.00
2 TI 16499.00 164.00
3 Recursos Humanos 42499.00 86.00
Thanks
There is probably duplication happening because of the double table join. One way around this is to aggregate each table in separate subqueries, and then join to them:
SELECT
d.id,
d.Nome_Dep,
COALESCE(f.sum_salario, 0) AS sum_salario,
COALESCE(dd.sum_revenue, 0) AS sum_revenue
FROM #Departamentos d
LEFT JOIN
(
SELECT ID_Dep, SUM(salario) AS sum_salario
FROM #Funcionarios
GROUP BY ID_Dep
) f
ON d.ID = f.ID_Dep
LEFT JOIN
(
SELECT ID_Deal, SUM(revenue) AS sum_revenue
FROM #deals
GROUP BY ID_Deal
) dd
ON d.ID = dd.ID_Deal;
Demo

How to use output variable in insert query

I am inserting records from our crm to our erp. The phone table uses a identity column from the people table. I need to insert the people record and capture the value in the PersonId which is an identity column and then use that PersonId as the key to insert records to the Phone table. I get the error:
Msg 137, Level 16, State 1, Line 16
Must declare the scalar variable "#IdentityID".
Msg 137, Level 16, State 1, Line 17
Must declare the scalar variable "#IdentityID".
--IdentityTable
CREATE TABLE [dbo].[People](
[People_ID] [int] NOT NULL,
[text] [nvarchar](50) NULL,
[PersonId] [int] IDENTITY(1,1) NOT NULL
) ON [PRIMARY]
--Phone
CREATE TABLE [dbo].[Phone](
[PersonId] [int] NOT NULL,
[text] [nvarchar](50) NULL,
[Number] [nchar](10) NULL
) ON [PRIMARY]
declare #IdentityID table (PersonId int);
INSERT INTO [Bridge].[dbo].[People]
([People_ID]
,[text])
output Inserted.PersonId into #IdentityID
VALUES
(3,'row1'),
(4,'row2');
INSERT INTO [Bridge].[dbo].[Phone]
(PersonId
,[text]
,[Number])
VALUES
(#IdentityID,'row1'),
(#IdentityID,'row2');
Print 'IdentityID' + #IdentityID
Msg 137, Level 16, State 1, Line 16
Must declare the scalar variable "#IdentityID".
Msg 137, Level 16, State 1, Line 17
Must declare the scalar variable "#IdentityID".
Output will be to tablevariable you can use as below:
declare #IdentityID table (PersonId int);
INSERT INTO [dbo].[People]
([People_ID]
,[text])
output Inserted.PersonId into #IdentityID(PersonId)
VALUES
(3,'row1'),
(4,'row2');
INSERT INTO [dbo].[Phone]
(PersonId
,[text]
,[Number])
select PersonId,'row1', 1 from #IdentityID
union all select PersonId,'row2', 2 from #IdentityID
select * from #IdentityID

PostgreSQL: Iterate through a tables rows with for loop, retrieve column value based on current row

I have the following 2 tables
CREATE TABLE salesperson_t (
salespersonid numeric(4,0) NOT NULL,
salespersonname character varying(25),
salespersontelephone character varying(50),
salespersonfax character varying(50),
salespersonaddress character varying(30),
salespersoncity character varying(20),
salespersonstate character(2),
salespersonzip character varying(20),
salesterritoryid numeric(4,0),
CONSTRAINT salesperson_pk PRIMARY KEY (salespersonid)
);
INSERT INTO salesperson_t VALUES (1, 'Doug Henny', '8134445555', NULL, NULL, NULL, NULL, NULL, 2);
INSERT INTO salesperson_t VALUES (2, 'Robert Lewis', '8139264006', NULL, '124 Deerfield', 'Lutz', 'FL', '33549', 13);
INSERT INTO salesperson_t VALUES (3, 'William Strong', '3153821212', NULL, '787 Syracuse Lane', 'Syracuse', 'NY', '33240', 3);
INSERT INTO salesperson_t VALUES (4, 'Julie Dawson', '4355346677', NULL, NULL, NULL, NULL, NULL, 4);
INSERT INTO salesperson_t VALUES (5, 'Jacob Winslow', '2238973498', NULL, NULL, NULL, NULL, NULL, 5);
INSERT INTO salesperson_t VALUES (6, 'Pepe Lepue', NULL, NULL, NULL, 'Platsburg', 'NY', NULL, 13);
INSERT INTO salesperson_t VALUES (8, 'Fred Flinstone', NULL, NULL, '1 Rock Lane', 'Bedrock', 'Ca', '99999', 2);
INSERT INTO salesperson_t VALUES (9, 'Mary James', '3035555454', NULL, '9 Red Line', 'Denver', 'CO', '55555', 4);
INSERT INTO salesperson_t VALUES (10, 'Mary Smithson', '4075555555', NULL, '4585 Maple Dr', 'Orlando', 'FL', '32826', 15);
CREATE TABLE territory2_t (
territoryid numeric(4,0),
territoryname character varying(50),
total_sales_person integer,
CONSTRAINT territory2_t_pk PRIMARY KEY (territoryid)
);
INSERT INTO territory2_t VALUES (1, 'SouthEast', NULL);
INSERT INTO territory2_t VALUES (2, 'SouthWest', NULL);
INSERT INTO territory2_t VALUES (3, 'NorthEast', NULL);
INSERT INTO territory2_t VALUES (4, 'NorthWest', NULL);
INSERT INTO territory2_t VALUES (5, 'Central', NULL);
INSERT INTO territory2_t VALUES (6, 'Alaska', NULL);
INSERT INTO territory2_t VALUES (12, 'Hawaii', NULL);
INSERT INTO territory2_t VALUES (13, 'Colorado', NULL);
INSERT INTO territory2_t VALUES (15, 'Arizona', NULL);
I have the following pseudo code:
DO $$
DECLARE
-- currentRow [relevant datatype];
BEGIN
FOR counter IN 1..(SELECT count(*)FROM territory2_t) LOOP -- There are 13 total rows
-- **assign currentRow to counter**
RAISE NOTICE 'Counter: %', counter; -- debugging purposes
UPDATE terriory2_t
SET total_sales_person = ((SELECT count(*)
FROM salesperson_t
WHERE salesterritoryid = currentRow.territoryid)*1) -- *1 is for debuggin puporses
WHERE territoryid = currentRow.territoryid;
-- **increase currentRow by 1**
END LOOP;
END; $$
It's purpose is count how many rows in the table (salesperson) have the 'territoryid' of the the currentRows->'territory2.territoryid', and then assign that quantity to currentRows->territory2.total_sales_person.
You don't need a loop or even a function for this.
What you want to do can be done in a single update statement because the total count per territory can be calculated with a single aggregation:
SELECT salesterritoryid, count(*) as total_count
FROM salesperson_t
group by salesterritoryid
This can then be used as the source to update the territory table:
UPDATE territory2_t
SET total_sales_person = t.total_count
FROM (
SELECT salesterritoryid, count(*) as total_count
FROM salesperson_t
group by salesterritoryid
) t
WHERE territoryid = t.salesterritoryid;
An alternative that might be easier to understand but will be slower for larger tables is an update with a co-related sub-query
UPDATE territory2_t tg
SET total_sales_person = (select count(*)
from salesperson_t sp
where sp.salesterritoryid = tg.territoryid);
There is a slight difference between the first and second update: the second one will update the total_sales_person to 0 (zero) for those territories where there is no salesperson at all. The first one will only update the count for territories that are actually present in the salesperson table.
Unrelated, but: having a "type identifying" prefix or suffix for an identifier is usually useless and doesn't really help at all. See a related discussion on dba.stackexchange