What does "error code MySql- 1052 Column 'x' in field list is ambiguous" mean? - sql-delete

I tried to delete from a table, and I got the following error: Error Code: 1052. Column 'clientID' in field list is ambiguous.
CREATE DATABASE dogsLife; use dogsLife;
CREATE TABLE Items ( ItemID int PRIMARY KEY, ItemDesc varchar(35), stock int, cost double);
CREATE TABLE Clients ( clientID int PRIMARY KEY, clientName varchar(35), Street varchar(35));
CREATE TABLE Orders ( OrdID int PRIMARY KEY, clientID int, OrderDate date, FOREIGN KEY (clientID) references Clients(clientID) );
CREATE TABLE Items_in_orders ( OrdID int, ItemID int, quantity int, FOREIGN KEY (OrdID) references Orders(OrdID), FOREIGN KEY (ItemID) references Items(ItemID), PRIMARY KEY (OrdID,ItemID) );
DELETE FROM Orders WHERE clientID IN (SELECT clientID FROM Clients INNER JOIN Orders ON Clients.clientID=Orders.clientID INNER JOIN Items_in_orders ON Orders.OrdID=Items_in_orders.OrdID INNER JOIN Items ON Items.ItemID=Items_in_orders.ItemID WHERE (quantity*cost)<100 AND street='Hess');
DELETE FROM Clients WHERE clientID IN (SELECT clientID FROM Clients INNER JOIN Orders ON Clients.clientID=Orders.clientID INNER JOIN Items_in_orders ON Orders.OrdID=Items_in_orders.OrdID INNER JOIN Items ON Items.ItemID=Items_in_orders.ItemID WHERE (quantity*cost)<100 AND street='Hess');

Use Clients.clientId instead of just clientID in the WHERE clause. Otherwise , the MySQL engine doesn't know if you're trying to reference the primary key on the first table or the foreign key of another table inside the join

Related

Postgres: change primary key in existing table

I have a situation with two tables where one has a foreign key pointing to the other table (simplified) schema:
CREATE TABLE table1 (
name VARCHAR(64) NOT NULL,
PRIMARY KEY(name)
);
CREATE TABLE table2 (
id SERIAL PRIMARY KEY,
table1_name VARCHAR(64) NOT NULL REFERENCES table1(name)
);
Now I regret using the name column as primary key in table1 - and would like to add integer serial key instead. Since I already have data in the database I guess I need to do this carefully. My current plan is as follows:
Drop the foreign key constraint: table2(name) with ALTER TABLE table2 DROP CONSTRAINT table2_table1_name_fkey;
Drop the primary key constraint on table1(name) with ALTER TABLE table1 DROP CONSTRAINT name_pkey;.
Add a unique constraint on table1(name) with ALTER TABLE table1 ADD UNIQUE(name);
Add a automatic primary key to table1 with ALTER TABLE table1 ADD COLUMN ID SERIAL PRIMARY KEY;.
Add a new column table1_id to table2 with ALTER TABLE table2 ADD COLUMN table1_id INT;
Update all rows in table2 - so that the new column (which will be promoted to a foreign key) gets the correct value - as inferred by the previous (still present) foreign key table1_name.
I have completed steps up to an including step 5, but the UPDATE (with JOIN?) required to complete 6 is beyond my SQL paygrade. My current (google based ...) attempt looks like:
UPDATE
table2
SET
table2.table1_id = t1.id
FROM
table1 t1
LEFT JOIN table2 t2
ON t2.table1_name = t1.name;
You do not need JOIN in UPDATE.
UPDATE
table2 t2
SET
table1_id = t1.id
FROM
table1 t1
WHERE
t2.table1_name = t1.name;

How to update table on postgres with join statement

I have three tables on postgresql DB, and tried to update table but I failed to get result what I want. Please help me with getting valid result.
The first table is "employee".
On this table, the first three characters of "employee_id" mean employee type.
For example, employee_id="AA1-11111" is a member of employee_type="AA1".
employee_id
department
AA1-11111
A
AA1-22222
B
AB1-11111
A
The second table is "assessment".
On this table, assessment criteria is defined for (employee_type, department).
For example, an employee of employee_type="AA1" and department="A" will be evaluated by assessment_criteria="XX1X".
employee_type
department
assessment_criteria
AA1
A
XX1X
AA1
B
XX1Y
AA2
A
XX2X
The third table is "employee_assessment". On this table assessment_criteria for each employee is defined. (This table is calculated from "employee" and "assessment" by night batch processing.)
employee_id
department
assessment_criteria
AA1-11111
A
XX1X
AA1-22222
B
XX1Y
AB1-11111
A
Null
What I want to do is... to update "employee_assessment" table when "assessment" table is updated.
When "assessment" table is updated as like below...
employee_type
department
assessment_criteria
AA1
A
XX1X
AA1
B
NEW
AA2
A
Null
I want to update "employee_assessment" table like this.
employee_id
department
assessment_criteria
AA1-11111
A
XX1X
AA1-22222
B
NEW
AB1-11111
A
Null
I tried
UPDATE
employee_assessment
SET assessment_criteria=employee_assessment.assessment_criteria
FROM employee
LEFT JOIN (SELECT employee_id, LEFT(employee_id,3) as emp_type, department as emp_department from employee) as t1
ON
employee.employee_id=t1.employee_id
and
employee.department=t1.emp_department
left join assessment
on
t1.emp_type=assessment.employee_type
and
t1.emp_department=assessment.department;
But I got this result.
employee_id
department
assessment_criteria
AA1-11111
A
XX1X
AA1-22222
B
XX1X
AB1-11111
A
XX1X
My query seems to be wrong.
The actual cause of the problem is that you schema isn't properly normalized. Therefore you should solve this by fixing and normalizing your schema. Then you can simply use a view, that is "updated" automatically.
First have tables for the types and departments (unless you have that already (that's unclear)).
CREATE TABLE type
(id serial,
name varchar(64),
PRIMARY KEY (id));
CREATE TABLE department
(id serial,
name varchar(64),
PRIMARY KEY (id));
Then, in the table for the employees, just reference the types and departments. Don't have a column that actually are two columns, i.e. the type id has to have its own column and must not be concatenated to any other.
CREATE TABLE employee
(id serial,
type integer,
department integer,
given_name varchar(64),
surname varchar(64),
PRIMARY KEY (id),
FOREIGN KEY (type)
REFERENCES type
(id),
FOREIGN KEY (department)
REFERENCES department
(id));
In the table for the assessments reference the types and departments too.
CREATE TABLE assessment
(id serial,
type integer,
department integer,
name varchar(64),
criteria varchar(64),
PRIMARY KEY (id),
FOREIGN KEY (type)
REFERENCES type
(id),
FOREIGN KEY (department)
REFERENCES department
(id));
Now you can create view for the employee assessments that joins the data from the other tables and is always up to date. There's no need for any manual UPDATE.
CREATE VIEW employee_assessment
AS
SELECT e.id employee_id,
e.department employee_department,
a.criteria assessment_criteria
FROM employee e
LEFT JOIN assessment a
ON a.type = e.type
AND a.department = e.department;
A view also has the advantage that it cannot contain inconsistent data as the table you have now could.

Merging columns from 2 different tables to apply aggregate function

I have below 3 Tables
Create table products(
prod_id character(20) NOT NULL,
name character varying(100) NOT NULL,
CONSTRAINT prod_pkey PRIMARY KEY (prod_id)
)
Create table dress_Sales(
prod_id character(20) NOT NULL,
dress_amount numeric(7,2) NOT NULL,
CONSTRAINT prod_pkey PRIMARY KEY (prod_id),
CONSTRAINT prod_id_fkey FOREIGN KEY (prod_id)
REFERENCES products (prod_id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
Create table sports_Sales(
prod_id character(20) NOT NULL,
sports_amount numeric(7,2) NOT NULL,
CONSTRAINT prod_pkey PRIMARY KEY (prod_id),
CONSTRAINT prod_id_fkey FOREIGN KEY (prod_id)
REFERENCES products (prod_id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
I want to get the Sum and Average sales amount form both the tables(Only for the Selected Prod_id). I have tried the below code but it's not producing any value.
select sum(coalesce(b.dress_amount, c.sports_amount)) as total_Amount
from products a JOIN dress_sales b on a.prod_id = b.prod_id
JOIN sports_sales c on a.prod_id = c.prod_id and a.prod_id = ANY( {"123456","456789"}')`
Here 1000038923 is in dress_sales table and 8002265822 is in sports_sales.
Looks like your product can exist in only one table (dress_sales or sports_sales).
In this case you should use left join:
select
sum(coalesce(b.dress_amount, c.sports_amount)) as total_amount,
avg(coalesce(b.dress_amount, c.sports_amount)) as avg_amount
from products a
left join dress_sales b using(prod_id)
left join sports_sales c using(prod_id)
where
a.prod_id in ('1', '2');
If you use inner join (which is default) the product row will not appear in the result set as it will not be joined with either dress_sales or sports_sales.
If you have a product that appears in both tables you can use a subquery that can handle both dress_amount and sports_amount values.
select sum(combined.amount), avg(combined.amount)
from
(select prod_id, dress_amount as amount from dress_sales
union all
select prod_id, sports_amount as amount from sports_sales) combined
where
combined.prod_id in ('1','2');

Should I add the primary key in my sql server index?

I know any non clustered index contains the primary key. But I wonder if it contains it in a specific order or not.
I have a query which retrieve for every "MemberTee" its most recent (highest ID) "MemberTeeHist"'s teeID value.
SELECT
MT.ID
, MTH.teeID
FROM Favorite.tMemberTee AS MT
INNER JOIN (
SELECT
MTH.memberTeeID
, MTH.teeID
, ROW_NUMBER() OVER (PARTITION BY MTH.memberTeeID ORDER BY MTH.ID DESC) AS RNK
FROM Favorite.tMemberTeeHist AS MTH
) AS MTH ON (
MTH.memberTeeID = MT.ID
AND
MTH.RNK = 1
)
In order for this query to perform the best, I need an index on tMemberTeeHist ordered by memberTeeID and ID (primary key).
Here are the tables DDL :
CREATE SCHEMA Favorite
GO
CREATE TABLE Favorite.tMemberTee (
ID INT NOT NULL IDENTITY
, CONSTRAINT PK_tMemberTee PRIMARY KEY (ID)
, memberID BIGINT NOT NULL
, CONSTRAINT FK_tMemberTee_memberID FOREIGN KEY (memberID) REFERENCES dbo.tMembers(ID)
, courseID INT NOT NULL
, CONSTRAINT FK_tMemberTee_courseID FOREIGN KEY (courseID) REFERENCES dbo.tCourseBases(ID) ON DELETE CASCADE
, CONSTRAINT UQ_tMemberTee_01 UNIQUE (courseID, memberID)
)
GO
CREATE TABLE Favorite.tMemberTeeHist (
ID INT NOT NULL IDENTITY
, CONSTRAINT PK_tMemberTeeHist PRIMARY KEY (ID)
, memberTeeID INT NOT NULL
, CONSTRAINT FK_tMemberTeeHist_memberTeeID FOREIGN KEY (memberTeeID) REFERENCES Favorite.tMemberTee(ID) ON DELETE CASCADE
, teeID INT NOT NULL
, CONSTRAINT FK_tMemberTeeHist_teeID FOREIGN KEY (teeID) REFERENCES dbo.tTees(ID)
, [date] DATETIME NOT NULL CONSTRAINT DF_tMemberTeeHist_date DEFAULT GETDATE()
, originatorID INT NOT NULL
, CONSTRAINT FK_tMemberTeeHist_originatorID FOREIGN KEY (originatorID) REFERENCES dbo.tClubMembers(ID)
)
GO
Now, should I create the index this way (because SQL SERVER would already internally have ID ordered inside the index) :
CREATE NONCLUSTERED INDEX IDX_tMemberTeeHist_memberTeeID ON Favorite.tMemberTeeHist (memberTeeID ASC)
GO
Or should I have it like this :
CREATE NONCLUSTERED INDEX IDX_tMemberTeeHist_memberTeeID ON Favorite.tMemberTeeHist (memberTeeID ASC, ID ASC)
GO
Since the constraint
CONSTRAINT PK_tMemberTee PRIMARY KEY (ID)
creates a default, clustered primary key (and thus a clustered index), that clustering column ID is already part of every nonclustered index (at the leaf level) anyway
There's no point or no benefit in adding it in separately again.

Looking up values from many tables based on value in each column

I have several tables containing key value pairs for differint fields in my database. I also have a table that that contains the keys of these differint tables that should be selected as the value for that key. However, I can't figure out how to select these values from the multiple tables?
The tables
CREATE TABLE CHARACTERS(
ID INTEGER PRIMARY KEY,
NAME VARCHAR(64)
);
CREATE TABLE MEDIA(
ID INTEGER PRIMARY KEY,
NAME VARCHAR(64)
);
CREATE TABLE EPISODES(
ID INTEGER PRIMARY KEY,
MEDIAID INTEGER,
NAME VARCHAR(64)
);
-- Selecting from this table
CREATE TABLE APPS(
ID INTEGER PRIMARY KEY,
CHARID INTEGER,
EPISODEID INTEGER,
MEDIAID INTEGER
);
I am selecting from the APPS table, and I want to replace the value of the *ID columns with the value of the name in the accomping table's NAME column. I want this done for each row in the APPS table. Like so...
CHARID -> CHARACTERS.NAME
EPISODEID -> EPISODES.NAME
MEDIAID -> MEDIA.NAME
I have tried to use joins, but they don't do it for each row in the APPS table. I have 18 rows in the APPS table, but I only get back way less than I have in the table or way more than I have in the table. So how can I make it do it for each row in the APPS table?
You do by JOINing the tables together and selecting the desired columns from the individual tables:
SELECT c.name AS character_name, e.name AS episode, m.name AS media
FROM apps a
LEFT JOIN episodes e ON e.id = a.episodeid
LEFT JOIN media m ON m.id = a.mediaid
LEFT JOIN characters c ON c.id = a.charid;
If you want to present the rows in a specific order, you can specify that too as a final clause in the SELECT statement. You can use any field from the included tables; that field is not necessarily part of the columns selected:
ORDER BY a.id -- order by apps.id
or
ORDER BY e.id, c.name -- order first by episode id, then by character name
etc