ORDER BY + IN statement? - sql

The marketing department wants to focus on the customers from Noth America first. Get the ID, last name and country of all customers. Build the list by bringing up the customers living in Canada and in the USA first, and finally order them by ID. Tip: use the IN expression in the ORDER BY clause.
I've tried many times
SELECT CustomerID, LastName, Country
FROM Customer
ORDER BY Country IN ('Canada', 'USA'), CustomerID
but it doesn't seem to work, as it takes the specified fields from all customers in the order they appear in the original table (which is also ordered by ID), even if I remove CustomerID from the ORDER BY clause, whithout caring to which country they belong to.
What should I do? I'm really new to SQL, and have no idea on how to fix this.
Edit: WHERE ins't suitable at all, as I need to take in consideration all customers, only making sure the Canadian and American ones appear at the top of the list.
Also I'm unsure statements like UNION, AS, EXCEPT and things like that are meant to be used, because the tutorial didn't go that deep already.

Not every DBMS has a boolean datatype. So the result of
Country IN ('Canada', 'USA'),
which is a boolean, can not be sorted in these DBMS.
You can use a CASE expression, however, to assign a value:
SELECT CustomerID, LastName, Country
FROM Customer
ORDER BY CASE WHEN Country IN ('Canada', 'USA') THEN 1 ELSE 2 END, CustomerID;

SELECT CustomerID, LastName, Country
FROM Customer
ORDER BY Country IN ('Canada', 'USA') desc, CustomerID asc

IN expression don't return value so you can't sort
You can try:
SELECT CustomerID, LastName, Country
FROM Customer
WHERE Country='Canada'
UNION ALL
SELECT CustomerID, LastName, Country
FROM Customer
WHERE Country='USA'
ORDER BY CustomerID
Using ORDER BY with UNION, EXCEPT, and INTERSECT When a query uses the
UNION, EXCEPT, or INTERSECT operators, the ORDER BY clause must be
specified at the end of the statement and the results of the combined
queries are sorted. The following example returns all products that
are red or yellow and sorts this combined list by the column
ListPrice.
https://msdn.microsoft.com/en-us/library/ms188385.aspx#Union

Related

How to use where condition for two conditions in same column in SQL Server

I have two tables, Customer and Sales.
I have to select customer and salesperson in the query. I have combined both the tables with the primary key with customer ID .
I also have to filter the selected data where salesperson name is ‘ John’ and ‘jack ,
When I use
where salesperson = ‘John’ and ‘jack’
I am getting no results.
Please help me on how to get salesperson with names from jack and John .
You would use in:
where salesperson in ('John', 'Jack')
This is logically equivalent to:
where salesperson = 'John' or salesperson = 'Jack'
But in is simpler to write and less error-prone.
If you want customers that have been associated with both John and Jack, then you would combine this with aggregation:
select customerid
from sales
where salesperson in ('John', 'Jack')
group by customerid
having count(distinct salesperson) = 2;
That is, look for customers that have either saleperson. Aggregate and return only the customers that have had both.
AND is correct. Using OR as wouter suggests will output the result if 1 condition is matched so probably not what you want. Perhaps paste the full code here for better help. Have you tested just 1 name or OR just to ensure your query is working?

Remove Duplicates from SQL Query

I am using this query currently to trigger a customer event. But sometimes the same customer will be in the results because they are assigned a different WorkOrderId, which is my primary filter. So, I want to expand the filter to also look for a unique CustomerName. In other words, if the query returns two rows with the same CustomerName then I want it to exclude the 2nd row altogether.
SELECT CustomerName, JobId, Email, CCEmail, WorkOrderId AS id
FROM dbo.vwWorkOrderDetail
WHERE JobStatusId=3 AND Active=1 AND LocationStopTypeId=1
ORDER BY WorkOrderId DESC
I've tried using DISTINCT but I continue to get results that include the same CustomerName in different rows. How can I setup this query so it returns results that passed all of the WHERE conditions and then only shows rows with a unique CustomerName?
As long as you include WorkOrderId, DISTINCT will do nothing for you. DISTINCT can only eliminate duplicates where all of the columns specified in the SELECT contain the same information. So to use DISTINCT to eliminate duplicate customers, you would need to do this:
SELECT DISTINCT CustomerName, JobId, Email, CCEmail
FROM dbo.vwWorkOrderDetail
WHERE JobStatusId=3 AND Active=1 AND LocationStopTypeId=1
ORDER BY WorkOrderId DESC
The best way to approach this to preserve a WorkOrderId is to make a new view based on the underlying tables. You will need to decide what WorkOrderId of the available WorkOrderIds you want to present. Typically this is the highest ID. If all you need is the WorkOrderId itself and not the details, this is actually pretty simple. Note the code below is a naïve example that assumes CustomerId is tied directly to a work order. To really answer this properly you'd need to provide the code for vwWorkOrderDetail.
SELECT CustomerName, JobId, Email, CCEmail, (SELECT MAX(WorkOrderId) FROM WorkOrders WHERE CustomerID = Customers.CustomerID) AS WorkOrderID
FROM Customers
WHERE JobStatusId=3 AND Active=1 AND LocationStopTypeId=1
ORDER BY WorkOrderId DESC
SELECT CustomerName, JobId, Email, CCEmail, max(WorkOrderId) AS id
FROM dbo.vwWorkOrderDetail
WHERE JobStatusId=3 AND Active=1 AND LocationStopTypeId=1
GROUP BY CustomerName, JobId, Email, CCEmail

sql query for the following statement?

My table 'Customer' contains customerid , firstname, lastname, company,city,state,country, email, invoicetotal
Question: For countries that have at least two customers using yahoo as email provider, display the name alongside the revenue
My solution:
select county,sum(invoiceTotal)from customer where email like '%yahoo%'
group by Country,Email having Count(Country)>2
I am unable to get proper result the no of rows displayed in my output are different from the number of rows in expected output,Can any1 tell me where have i gone wrong???
You are grouping by email as well - just group by Country and you should be fine
select
county,
sum(invoiceTotal)
from customer
where email like '%yahoo%'
group by Country
having Count(Country)>2
You can't group by email, since that's unique. Fortunately, you don't have to.
select
county,
sum(invoiceTotal)
from customer
where email like '%yahoo%'
group by Country
having Count(Country)>=2
Because the statement say at least then you need put >=.

SQL Homework - "IN" Subquery

yes this is a homework question, but I'm giving it honest effort and I'm not asking you to do it for me, just point me in the right direction! :)
So I have a set of questions concerning the SQL IN subquery, and while I understand what it does I'm having trouble applying it in these situations.
The first question:
1) Use the In subquery technique to list the customer number, customer name and phone for customers who have paid either by visa or mc. Sort
by customer name.
This one I believe I got:
SELECT DISTINCT
tblCust.CustomerNum, CustomerName, Phone
FROM
tblCust
INNER JOIN tblOrd ON
tblCust.CustomerNum=tblOrd.CustomerNum
WHERE
tblOrd.PayMethod IN ("visa", "mc")
ORDER BY CustomerName;
But the next one just makes no sense to me:
2) Use the In subquery technique to list from tblCust the customer number, customer name and state for customers who have a state
description that begins with “co”.
Shouldn't I be using the LIKE operator for this instead of IN?
So far I have:
SELECT
CustomerNum, CustomerName, StateProv
FROM
tblCust
INNER JOIN tblState ON
tblCust.StateProv = tblState.StateProv
WHERE
tblState.StateProvDesc IN
And I don't know what to put after the IN, if I were using LIKE I would say
...StateProvDesc LIKE "co%"
and be done with it, but I don't think that's what my teacher wants.
Finally, the third question:
3) Use the In subquery technique to list from tblCust the customer
name, country for customers who have at least one order in the range
of $90,000-$120,000. Sort by country then customer name.
Shouldn't between be used for a range of numbers?
Thanks for anything you guys can think of!
using microsoft access by the way
I think what the prof wants you to do is write a subquery within the IN clause. You can actually put a select statement within IN() like this:
SELECT
CustomerNum, CustomerName, StateProv
FROM
tblCust
WHERE StateProv IN(SELECT StateProv FROM tblState WHERE StateProvDesc LIKE 'co%')
I think the instructor wants you to change the query to use ... IN (SELECT ... FROM ...) style instead of the inner join.
You can work on these queries from the back of the description, like this:
...a state description that begins with “co”.
-- Inner query
SELECT StateProv
FROM tblState
WHERE StateProvDesc LIKE `co%`
Now that you have this, you can compose the outer query:
list from tblCust the customer number, customer name and state for customers who have...
SELECT
CustomerNum, CustomerName, StateProv
FROM
tblCust
WHERE tblCust.StateProv IN (
-- Your inner query goes here
)

Return all Fields and Distinct Rows

Whats the best way to do this, when looking for distinct rows?
SELECT DISTINCT name, address
FROM table;
I still want to return all fields, ie address1, city etc but not include them in the DISTINCT row check.
Then you have to decide what to do when there are multiple rows with the same value for the column you want the distinct check to check against, but with different val;ues in the other columns. In this case how does the query processor know which of the multiple values in the other columns to output, if you don't care, then just write a group by on the distinct column, with Min(), or Max() on all the other ones..
EDIT: I agree with comments from others that as long as you have multiple dependant columns in the same table (e.g., Address1, Address2, City, State ) That this approach is going to give you mixed (and therefore inconsistent ) results. If each column attribute in the table is independant ( if addresses are all in an Address Table and only an AddressId is in this table) then it's not as significant an issue... cause at least all the columns from a join to the Address table will generate datea for the same address, but you are still getting a more or less random selection of one of the set of multiple addresses...
This will not mix and match your city, state, etc. and should give you the last one added even:
select b.*
from (
select max(id) id, Name, Address
from table a
group by Name, Address) as a
inner join table b
on a.id = b.id
When you have a mixed set of fields, some of which you want to be DISTINCT and others that you just want to appear, you require an aggregate query rather than DISTINCT. DISTINCT is only for returning single copies of identical fieldsets. Something like this might work:
SELECT name,
GROUP_CONCAT(DISTINCT address) AS addresses,
GROUP_CONCAT(DISTINCT city) AS cities
FROM the_table
GROUP BY name;
The above will get one row for each name. addresses contains a comma delimted string of all the addresses for that name once. cities does the sames for all the cities.
However, I don't see how the results of this query are going to be useful. It will be impossible to tell which address belongs to which city.
If, as is often the case, you are trying to create a query that will output rows in the format you require for presentation, you're much better off accepting multiple rows and then processing the query results in your application layer.
I don't think you can do this because it doesn't really make sense.
name | address | city | etc...
abc | 123 | def | ...
abc | 123 | hij | ...
if you were to include city, but not have it as part of the distinct clause, the value of city would be unpredictable unless you did something like Max(city).
You can do
SELECT DISTINCT Name, Address, Max (Address1), Max (City)
FROM table
Use #JBrooks answer below. He has a better answer.
Return all Fields and Distinct Rows
If you're using SQL Server 2005 or above you can use the RowNumber function. This will get you the row with the lowest ID for each name. If you want to 'group' by more columns, add them in the PARTITION BY section of the RowNumber.
SELECT id, Name, Address, ...
(select id, Name, Address, ...,
ROW_NUMBER() OVER (PARTITION BY Name ORDER BY id) AS RowNo
from table) sub
WHERE RowNo = 1