Multi-part Identifier could not be bound exception - sql-server

As a note I have searched around for quite a bit but could not seem to grasp on how to fix it still. I am still learning the ins and outs in SQL server so please be patient with me.
I want to get a desired output of quantity from two tables but when I start to add the subquery into my statement I would get this error:
The multi-part identifier "OD.Menu Name ID" could not be bound.
This is the statement that I have.
Select IT.[Item Name], SUM(OD.Quantity) * SI.Quantity as QTY from [Order Detail_T] as OD,
dbo.SumOfIngredientsQty_V as SI
join [Ingredients Qty_T]
on [Ingredients Qty_T].[Menu Name ID] = OD.[Menu Name ID]
join Ingredients_T as It
on [Ingredients Qty_T].[Ingredients ID] = IT.[Ingredients ID]
where SI.Quantity in (Select SumOfIngredientsQty_V.Quantity as SI from SumOfIngredientsQty_V)
Group by IT.[Item Name]
I have also created a view that correlates to the above statement:
create view SumOfIngredientsQty_V
as
Select [Item Name], Sum(Quantity) as Quantity from [Ingredients Qty_T]
join [Ingredients_T]
on [Ingredients Qty_T].[Ingredients ID] = Ingredients_T.[Ingredients ID]
group by [Item Name]
go
Can someone enlighten me on why I would get the "could not be bound" exception. Also if need be I can include the relationship of the tables.
Edit Here are the relationships (I could not upload an image but I hope this will do)
Ingredients_T : (PK) Ingredients ID, Item Name
Ingredients Qty_T : (FK) Menu Name ID, (FK) Ingredients ID, Quantity
Menu Name_T : (PK) Menu Name ID, Price, Menu Name
Order Detail_T : (PK) Order Detail ID, (FK) Order ID, (FK) Menu Name ID, Quantity
Ingredients_T > Ingredients Qty_T < Menu Name_T > Order Detail_T
The (<) signify where the PK goes to.

Check your spelling on OD.[Menu Name ID] Make sure that you have not omitted an underbar or any whitespace.
You can output the column names as SQL Server has them stored by using a query like:
select c.name as colname, t.name as tablename
from sys.columns c
join sys.tables t on c.object_id = t.object_id
where c.name like '%Menu%'
order by tablename
Above query restricts columns and tables to those that have a column with "Menu" somewhere in the name.

Related

Querying temporal table with date/time fields

I need to write a query to get following output using temporal table feature in SQL server 2016.
Customer Table (system versioned table)
Id
Name
[period_start] [datetime2](7) GENERATED ALWAYS AS ROW START NOT NULL
[period_end] [datetime2](7) GENERATED ALWAYS AS ROW END NOT NULL
Orders Table
Id
CustomerId
..
[creation_date] DATETIME default SYSUTCDATETIME()
Output : OrderId, ... , Customer Name
Customer name should be the reflect the correct name which relevant to the order date
Following query will give me the required output but I need to check whether this is the correct way of doing this type of queries..
SELECT T.Id, O.Name
FROM Orders T
INNER JOIN (
SELECT *
FROM Customer
FOR SYSTEM_TIME FROM '1900-01-01' TO '9999-12-31 23:59:59.9999999'
) O ON T.CustomerId = O.ID
AND T.creation_date BETWEEN O.period_start AND O.period_end
Thanks in advance
Chaminda.
I see nothing wrong with it, except perhaps the nested query is unnecessary:
SELECT T.Id, O.Name
FROM Orders T
JOIN Customer FOR SYSTEM_TIME FROM '1900-01-01' TO '9999-12-31 23:59:59.9999999' O
ON T.CustomerId = O.ID
WHERE T.creation_date BETWEEN O.period_start AND O.period_end
You seem to have extraneous criteria in your query. I think this does everything you've asked for:
SELECT T.Id, O.Name
FROM Orders T INNER JOIN Customer O
ON T.CustomerId = O.ID

How to do sub-query correctly while selecting two tables in Oracle?

I need to do a sub-query from a table to find all employees working in the same department that is part of the same city, but I'm not getting it.
I have the following tables:
Table departments
DEPARTMENTS
department_id
department_name
location_id
Table locations
LOCATIONS
location_id
street_address
postal_code
city
state_province
country_id
Table employees
EMPLOYEES
employee_id
first_name
last_name
email
phone_number
hire_date
job_id
department_id
My code right now is something like that :
SELECT
firt_name,
department_id,
job_id
FROM employees
WHERE state_province = (SELECT state_province FROM locations
WHERE state_province = 'Sao Paulo');
The problem is that while I want to select state_province from the table locations, I can't select the name, department id and job id from the table employees. How can I select both tables while doing the sub-query ?
Anyway, sorry if I did something wrong in the code, I am new to sub-queries.
You could try doing a join between the two tables instead:
SELECT
e.firt_name,
e.department_id,
e.job_id,
l.* -- replace with columns you really want
FROM employees e
INNER JOIN locations l
ON e.state_province = l.state_province
WHERE
e.state_province = 'Sao Paulo';
I don't know which columns you want to select from locations, but it doesn't really make sense to do a join just for state_province alone, as the employees table already has this column. So I just included location.* as a placeholder which you can replace with the columns you actually want.
Edit:
A join is the way to go here IMO, but if you absolutely need to use a subquery, then you can move your current subquery from the WHERE clause to the SELECT clause:
SELECT
firt_name,
department_id,
job_id,
(SELECT l.state_province FROM locations l
WHERE e.state_province = l.state_province) state_province
FROM employees e;
Note that this will only work if there is one matching province. For this and performance reasons, my join query is probably what you would want to use in practice.
I think in your case, sub-query may not be necessary.
A join table can do the trick.
SELECT e.first_name, e.department_id, e.job_id, l.state_province
FROM employees e
LEFT JOIN departments d ON e.department_id = d.department_id
LEFT JOIN locations l ON d.location_id = l.location_id
WHERE l.state_province = 'Sao Paulo';

Using group by to update multiple records in an update query

I have two tables. Table1 has company data (Company ID, Company Name ...), so single record for each company.
Table2 has information about departments in that company (Department ID, Department Name, Company ID, Company Name ... ). So, second table might have n number of records where same company id is used.
Problem is one of our trigger failed to work properly, and no one noticed till now. So, when Company Name was updated in Table1, it never reflected in Table2.
To correct this, I have to do something like the below query:
Update Table2
Set
[Company Name] = (select [Company Name]
from Table1
where Table2.Company ID = Table1.Company ID)
Group By Table2.Company ID
Basically, I am trying to update all records in Table2 to use the same name as Table1, for each record in Table1.
I am a bit confused about how to create the inner select clause.
P.S. Sorry, it might be a bit confusing. Kindly do let me know how to reword it the best.
Don't need to use group by ...
UPDATE T2
SET [Company Nane] = T1.[Company Nane]
FROM Table1 T1
INNER JOIN Table2 T2
ON T1.[Company ID] = T2.[Company ID]
As other have mentioned: Remove GROUP BY and your query works fine.
GROUP BY is used to produce a result row in a query that is an aggregate of other rows. E.g. one record per company from your department table with the most busy department per company. You cannot update such a result record, for that record does not exist in the table. You can only update table records.
So remove GROUP BY from your query and you have it straight-forward.
Update DepartmentTable
Set [Company Name] =
(
select [Company Name]
from CompanyTable
where CompanyTable.[Company ID] = DepartmentTable.[Company ID]
);

Need help creating a query for a non-normalized database

I've never worked with a non-normalized database before, so I'll try and explain my problem as best I can. So I have two tables:
The customers table holds all the customers information, and the orders table holds all the orders that they have placed. I haven't listed all the fields in the tables, just the ones that I need. The customer number in both tables is not the primary key, but I'm inner joining on them anyway. So the problem I'm having is that I don't know how to make a query that:
Selects all the customers with their first name, last name, and email, and also show the most recent orderdate, most recent total, and most recent ordertype. I know that I have to use a max() aggregate for the date, but that's as far as I got. Please help a noob out.
You can try:
SELECT FirstName,
LastName,
Email,
OrderDate,
OrderTotal,
OrderType
FROM Customers AS C
INNER JOIN Order AS O
ON O.CustomerNumber = C.CustomerNumber AND
O.OrderDate = (
SELECT MAX (O1.OrderDate)
FROM Order AS O1
WHERE O1.CustomerNumber = C.CustomerNumber)
)
assuming that Orders.OrderDate is unique for each CustomerNumber, does this work for you? if a single CustomerNumber has more than one entry in Order for OrderDate, you'll get each of those rows.
select c.FirstName, c.LastName, c.Email, o.OrderDate, o.OrderTotal, o.OrderType
from Customers c
join
(select CusomterNumber, max(OrderDate) as MostRecentOrderDate
from Orders
group by CustomerNumber
) mro on mro.CustomerNumber=s.CustomerNumber
join Orders o on o.OrderDate=mro.MostRecentOrdeDate and
o.CustomerNumber=mro.CustomerNumber
Try this:
SELECT
Customers.*, Orders.*
FROM
Customers
JOIN
(SELECT
Customer_Number,
MAX(Order_Date) OrderDate
FROM
Orders
GROUP BY
Customer_Number
) as Ord ON Customers.Customer_Number = Ord.Customer_Number
JOIN Order ON Orders.Customer_Number = Ord.Customer_Number
If you are doing this with SQL Server use the query designer and basically all you want to do is do a join since you have two keys that are the same one in Customer Table ->Customer Join on Order->Customer alias the Customer table as C and Orders table as O
so for example
SELECT Customer.*, Orders.*
From Customer c, Orders O INNER JOIN O where C.Customer Number = O.Customer Number
This should be enough to get you started.. if you don't want all the fields then fully qualify the names for example
SELECT C.FirstName, C.LastName, O.OrderDate, O.OrderType FROM Customer C, Orders O
WHERE C.Customer NUmber = O.Customer Number //this is another way of doing a Join when working with the where Clause.

How to put a subquery within an aggregate subquery

I am using SQL-Server 2000 and am trying to find duplicates with certain conditions. Someone here helped me earlier with the duplicate part which was great, however, I can't figure out how to filter the duplicated cases further.
I need to move the "where" statement to the subquery so that I only get contractor duplicated names as opposed to all duplicated names which is what's happening with this code (the code is first finding all duplicates and then filtering out the contractors and I'd like it to do the opposite). The problem is that I'm mixing it into an aggregate statement and it's giving me an error. I tried to put in another subquery within the subquery but it still gave me an error.
Any help is appreciated. Here's a simpler (I'm learning) version of the code:
SELECT DISTINCT(c1.contactid) as 'ContactID', c1.lastname as 'Last Name', c1.firstname as 'First Name'
FROM contacts c1 INNER JOIN (SELECT lastname, firstname FROM contacts group by lastname, firstname
HAVING count(*)>1)
dups on c1.lastname=dups.lastname and c1.firstname=dups.firstname
WHERE (c1.contractor=1)
For the example code you have given, placing the where clause between the "from contacts" and "group by lastname, firstname" should do they trick.
i think this is what you want:
SELECT
contact.ContactId,
contact.FirstName,
contact.LastName
FROM contacts as contact
INNER JOIN
(
SELECT ContactID FROM contacts GROUP BY FirstName, LastName HAVING Count(*) > 1
) AS Dups
ON Dups.ContactId = contact.ContactId
WHERE
contact.isContractor = 1
you are very close. this will provide you a list of each individual record that has a matching record with the same first name and last name. Hope this helps
Select C.contactid As ContactID
, C.LastName As [Last Name]
, C.FirstName As [First Name]
From contacts C
Inner Join (
Select C1.LastName, C1.FirstName
From contacts As C1
Where C1.contractor = 1
Group By C1.LastName, C1.FirstName
Having Count(*) > 1
) As dups
On C.LastName = dups.LastName
And C.FirstName = dups.FirstName
Where C.contractor = 1
You are going to need the filter on contractor = 1 in both the subquery and the outer query. Otherwise, you might return people that happen to have the same name as a contractor and are duplicated.
Also, you do not need the Distinct keyword if ContactId is the primary key of the Contacts table.
Move the where clause to the subquery. It fill first filter out all non-contractors, and then group the remainder.
SELECT DISTINCT
c1.ContactId
,c1.lastname as 'Last Name'
,c1.firstname as 'First Name'
from contacts c1
inner join (select lastname, firstname
from contacts
where c1.contractor = 1
group by lastname, firstname
having count(*) > 1) dups
on c1.lastname = dups.lastname
and c1.firstname = dups.firstname
Oh, and unless there's a really good reason, you really don't want to include embedded spaces in your column aliases ("Last Name", "First Name").

Resources