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").
Related
I am trying to create a query that returns results excluding 4 specific values from a columns.
Here is my code:
SELECT CustomerID,
ContactName,
Country
FROM Customers
WHERE CustomerID IN (SELECT CustomerID
FROM Customers
WHERE (Country <> ('UK')('Australia')('Canada')));
This works if I exclude only one country but not multiple.
Thanks in advance for any help you can provide.
Use NOT IN operator
The list should be separated by comma no need to have open/close parenthesis for each value inside the list. Also you don't need sub-query just add the filter Where clause
SELECT CustomerID,
ContactName,
Country
FROM Customers
WHERE Country NOT IN ( 'USA', 'UK', 'Australia', 'Canada' )
Make sure you dont pass any NULL values inside the list because NOT IN fails when there is a NULL value present in the list
Select
CustomerID, ContactName, Country
From Customers
Where CustomerID NOT IN ('USA','UK','Australia','Canada');
You may consider defining excluded countries in a special table (e.g. ExcludedCountry). This will separate your data (excluded countries) from your logic (select customer not in excluded countries). In this case, your query can look like:
select CustomerID, ContactName, Country
from Customers C
left join ExcludedCountry EC ON EC.Name = C.CustomerID
where CustomerID IS NOT NULL
or
-- may be faster than above
select CustomerID, ContactName, Country
from Customers C
where not exists (
select 1
from ExcludedCountry EC
where EC.Name = C.CustomerID)
The advantage of this solution is an easier management of your excluded items.
Schema:
tablename : Picture_profile
personID, pictureNumber(count which increase upon adding a picture for an id there can be many pictures),pictureName, datePictureAdded
tablename : person
personID, phone, address, zip, city, email,country and many other columns
Query:
select personID, email,country
case when count(pictureNumber)>=1 then 'yes' else 'no' PictureIsUploaded
from person_profile
left join Picture_profile on Picture_profile.personID = person_profile.personID
group by personID, email,country
above query works fine and displays what ever I want but the question is
If I need to display all the columns. Am I supposed to do "group by"
for all the columns in select.
Is there a way where I can eliminate this group by?
This only works on fairly recent versions of Sql Server, but I'd use the APPLY operator:
SELECT p.*,
COALESCE(a.HasPicture, 'N') PictureIsUploaded
FROM person_profile p
OUTER APPLY
(
SELECT TOP 1 'Y' HasPicture
FROM Picture_profile pic
WHERE pic.personID = p.personID
) a
You could also do this as a correlated derived table (sub query):
SELECT p.*,
COALESCE(
(SELECT TOP 1 'Y'
FROM Picture_profile pic
WHERE pic.personID = p.personID)
, 'N') PictureIsUploaded
FROM person_profile p
The advantage of the APPLY operator over the correlated subquery is when you want more than one value from the chosen Picture_Profile record. This would allow you to include, for example, both the picturename and picturenumber fields in the results, but only incur the subquery cost once.
I am trying to build a single select statement from two separate ones.
Basically I have a list of Names in a table which do repeat like so:
Name| Date
John 2014-11-22
John 2013-02-03
Joe 2012-12-12
Jack 2011-11-11
Bob 2010-10-01
Bob 2013-12-22
I need to do a Select distinct Name from Records which returns John, Joe, Jack, Bob.
I then want to so a Select on another table where I pass in the rows returned above.
SELECT Address, Phone From dbo.Details
WHERE Name = {Values from first SELECT query}
Having trouble with the syntax.
If you do not want to return any values from the subquery, you can use either IN or EXISTS
SELECT Address, Phone From dbo.Details
WHERE Name IN (SELECT DISTINCT Name FROM Records)
-- OR --
SELECT Address, Phone From dbo.Details D
WHERE EXISTS (SELECT 1 FROM Records R WHERE R.Name = D.Name)
(In most RDBMS the EXISTS is less resource intensive).
If you want to return values from the subquery, you should use JOIN
SELECT
D.Address,
D.Phone,
R.Name -- For example
FROM
dbo.Details D
INNER JOIN dbo.Records R
ON D.Name = R.Name
SIDENOTE These are sample queries, it is possible that you have to fine tune them to match your exact requirements.
You can use:
SELECT Address, Phone, name
FROM details
-- "in" is the difference from your first query, needed due to multiple values being returned by the subquery
WHERE name in (
SELECT distinct name
FROM namesTable
)
Additionally the following should work:
SELECT d.Address, d.Phone, n.name
FROM details d
inner join (
select distinct name
from namesTable
) n on d.name = n.name
So there are two ways you can go about doing this. One, create a temporary table and perform a join (*actually in retrospect you could also join to your second table as a subquery, or use something like a CTE if you're using SQL SERVER, but the modifications if you wanted to go that route should be pretty obvious)
CREATE TEMPORARY TABLE my_table AS
{your first select query};
SELECT Address, Phone From dbo.Details
INNER JOIN my_table AS mt
ON mt.name = dbo.name
Another option would be to perform an IN or EXISTS query using your select query
SELECT Address, Phone From dbo.Details
WHERE name IN (SELECT name from my_table)
Or, better yet (eg SQL Server IN vs. EXISTS Performance),
SELECT Address, Phone From dbo.Details
WHERE EXISTS (SELECT * from my_table WHERE my_table.name = dbo.name)
You might have to modify the syntax slightly, depending on if you are using MySQL or SQL Server (not sure about that later, honestly). But this should get you started down the right path
This will give you the names and their address and phone number:
SELECT DISTINCT N.Name, D.Address, D.Phone
FROM dbo.Details D INNER JOIN dbo.Names N ON D.Name = N.Name
When using a subquery that is not scalar (doesn't return only one value) in the where clause use IN and of course only one column in the subquery:
SELECT Address, Phone
From dbo.Details
WHERE Name IN (Select Name from Table)
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.
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.