Query to output customers and employees and their cities where each city must contain at least one customer and one employee - sql

I must take sellers and customers and output them in one column, showing their cities and types.
My problem is: I don't need to output customers whose cities aren't in sellers' table and vice versa.
SELECT
ContactName, City, Type
FROM
(SELECT
'Seller' AS Type,
ContactName, City
FROM
[dbo].[Suppliers] t
GROUP BY
City, ContactName
UNION
SELECT
'Customer',
ContactName, City
FROM
[dbo].[Customers] t
GROUP BY
City, ContactName) t
GROUP BY
ContactName, City, Type
Result :
| Ivan Ivanov | Seller | Moscow |
| Piotr Petrov | Seller | Moscow |
| Ivan Romanov | Customer | Moscow |
| Johnny Bravo | Customer | London |
(let's assume there are no sellers in London therefore this column shouldn't exist)
Expected result: only columns with information where a city has at least one seller and one customer grouped by contact name and city

This seems like union all and exists:
SELECT DISTINCT c.ContactName, 'Customer' as type, c.City
FROM Customers c
WHERE EXISTS (SELECT 1 FROM Sellers s WHERE s.city = c.city)
UNION ALL
SELECT DISTINCT s.ContactName, 'Seller' as type, s.City
FROM Sellers s
WHERE EXISTS (SELECT 1 FROM Customers c WHERE c.city = s.city);
I'm not sure the SELECT DISTINCT is really needed -- I don't see why the underlying tables would have duplicates (although ContactName is not really a good column for unique identification). However, your original query has GROUP BY, suggesting that you want to eliminate duplicates.

Related

Oracle Sql Developer (Select Count) Twoc olumns

I have to make a query that has the Total number of customers by country and city
country and city are columns that are inside the customer table
On my own I have managed to get the total number of customers per city like this:
SELECT city, COUNT (*)
FROM employees
GROUP BY city
ORDER BY city
But how do I get it together with the country?
looking for information I think it should be something like this and ordered from largest to smallest
Country
City
TOTAL_CUSTOMERS
USA
Kirkland
3
USA
London
2
UK
Redmond
2
UK
Seattle
1
UK
Tacoma
1
What we have been told is to say Total number of customers by country and city.
You simply add country to the column list and group by list:
SELECT country,city, COUNT(*)
FROM employees
GROUP BY country,city
ORDER BY COUNT(*) DESC

Sql join in two tables and return empty tab as Unavaliable

In a SQL join, table 1 contains person info with city and table 2 contains city matched to country such as:-
Table #1
ID Name City
-------------------------
1 Kishan Pokhara
2 Ram Delhi
3 Shyam Beijing
Table #2
City Country
----------------------
Pokhara Nepal
Delhi India
I want to get the person ID, Name, Country so while joining the tables I want these items and if there is no country available for a city, I want "Unavailable" written in the country columns. Thanks
Try the below using left join and use coalesce() function to replace null country as 'Unavailable'
select id, name, a.city,coalesce(country,'Unavailable') as country
from table1 a left join table2 b on a.city=b.city

How do I keep only 1 result according the alphabetical order in a tie with SQL queries?

The question asked to take the city with the highest sum of goods that bought by customer for each country. Basically, there are cities that have the same number of goods, but we only keep the first one in alphabetical order. The result only contains country name, the city with highest number of goods and their goods in sum.
Table Schema:
Country table:
country_name
city_name
Goods table:
city_name
user_id
number_of_goods
My queries result:
France Paris 85
Germany Berlin 100
Germany Frankfurt 100
Germany Luxembourg 100
Netherlands Amsterdam 75
Spain Barcelona 93
The right result should be:
France Paris 85
Germany Berlin 100
Netherlands Amsterdam 75
Spain Barcelona 93
You can use row_number() :
select t.*
from (select t.*, row_number() over (partition by country order by city) as seq,
max(no_goods) over (partition by country) as max_good
from table t
) t
where seq = 1;
use aggregation functions min() for city and max() for no_of_goods.
select t1.country, t1.no_of_goods, min(t2.city) as city
from
(select country, max(no_of_goods) as no_of_goods from tableA
group by country) t1
left join tableA t2 on t2.no_of_goods = t1.no_of_goods and t1.country = t2.country
group by t1.country, t1.no_of_goods
see dbfiddle.
Basically, there are cities that have the same number of goods, but we only keep the first one in alphabetical order.
Based on your sample data, all cities in a country seem to have the same number_of_goods. If so, you can just use aggregation:
select c.country, min(c.city_name), max(number_of_goods)
from countries c join
goods g
on c.city_name = g.city_name
group by c.country;

SQLite percentages with small values

So I have this table of subscribers of users and the country they are in.
UserID | Name | Country
-------+-------------------+------------
1 | Zaphod Beeblebrox | UK
2 | Arthur Dent | UK
3 | Gene Kelly | USA
4 | Nat King Cole | USA
I need to produce a list of all the users by percentage from each of the countries. I also need all the smaller member countries (under 1%) to be collapsed into an "OTHERS" category.
I can accomplish a simple "top x" of members trivially with a
SELECT COUNTRY, COUNT(*) AS POPULATION FROM SUBSCRIBERS GROUP BY COUNTRY ORDER BY POPULATION DESC LIMIT 10
and can generate the percentages by PHP server side code, but I don't quite know how to:
Do all of it in SQL including percentage calculations directly in the result
Club all under 1% members into a single OTHERS category.
So I need something like this:
Country | Population
--------+-----------
USA | 25.4%
Brazil | 12%
UK | 5%
OTHERS | 65%
Appreciate the help!
Here is query for this, I used a subquery to count the total number of rows and then used that to get the percentage value for each. The 'Others' category was generated in a separate query. Rows are sorted by descending population with the Others row last.
SELECT * FROM
(SELECT country , ROUND((100.0*COUNT(*)/count_all),1) ||'%' AS population
FROM (SELECT count(*) count_all FROM subscribers) AS sq,
subscribers s
WHERE (SELECT 100*count(*)/count_all
FROM subscribers s2
WHERE s2.country = s.country) > 1
GROUP BY country
ORDER BY population DESC)
UNION ALL
SELECT 'OTHERS', IFNULL(ROUND(100.0*COUNT(*)/count_all,1),0.0) ||'%' AS population
FROM (SELECT count(*) count_all FROM subscribers) AS sq,
subscribers s
WHERE (SELECT 100*count(*)/count_all
FROM subscribers s2
WHERE s2.country = s.country) <= 1
Ok I think I might have found a way to do this that's a hell of a lot quicker on execution speed:
SELECT territory,
Round(Sum(percentage), 3) AS Population
FROM (SELECT
Round((Count(*)*100.0)/(SELECT Count(*) FROM subscribers),3) AS Percentage,
CASE
WHEN ((Count(*)*100.0)/(SELECT Count(*) FROM subscribers)) > 2 THEN
country
ELSE 'Other'
END AS Territory
FROM subscribers
GROUP BY country
ORDER BY percentage DESC)
GROUP BY territory
ORDER BY population DESC;

How to remove duplicate entries in SQL using selected columns only?

My data is as shown below:
id | name | date | country | vendor
1717 | CUST A | 8-Aug-1978 | INDIA | VENDOR 1
1972 | CUST B | 1-Jan-1965 | INDIA | VENDOR 2
2083 | CUST C | 1-Jan-1936 | AUSTRALIA | VENDOR 1
2189 | CUST D | 27-May-2000 | USA | VENDOR 4
2189 | CUST D | 27-May-2000 | USA | VENDOR 5
2189 | CUST D | 27-May-2000 | USA | VENDOR 6
Question:
I want to remove the duplicate rows based on Columns
id, name, date, gender and country only (hence excluding Vendor)
In the above example, the 5th and 6th entries are duplicate except for their vendors.
Using Select Query how can I get rid of the 5th and 6th entry and keep on 4th entry?
By Keeping the 4th Entry, I mean the first Entry that comes up by select in the sequence of rows.
One method is group by:
select id, name, date, gender, country, min(vendor) as vendor
from t
group by id, name, date, gender, country;
This returns an "arbitrary" value of vendor. Tables in SQL represent unordered sets. There is no concept of 4th or 5th or 6th row. So, if you want one of the particular vendor values, you need to specify how that value is determined.
SELECT count(vendor) as count, id, name, date, gender, country
FROM TABLENAME
GROUP BY id, name, date, gender, country
WHERE Count > 1
sqlcsa
You can use Row_Number()
select * from (
select *, RowN= Row_Number() over(partition by id, name, date, gender, country order by id, name, date, gender, country)
from YourTable ) a where a.RowN = 1
If you are not interested in preserving the vendor information, you can use the distinct keyword
select distinct id, name, date, gender, country
from yourTable
This way the rows that are different for the undesired column only, will result as identical and the distinct will have the query return only one of them
Edit
If you want to preserve only the rows that are not duplicate, you can first select the combinations of id, name, date, gender and country that are available only once
select id, name, date, gender, country, count(*)
from yourTable
group by id, name, date, gender, country
having count(*) = 1
Then you use this table to filter the original one, by joining them together
select t1.*
from yourTable t1
join (
select id, name, date, gender, country, count(*)
from yourTable
group by id, name, date, gender, country
having count(*) = 1
) t2
on t1.id = t2.id and
t1.name = t2.name and
t1.date = t2.date and
t1.gender = t2.gender and
t1.country = t2.country