How do I nest two count() statements? - mysql

Imagine a three-column table, let's say TRAVELS with the columns NAME, and COUNTRY which they've ever been to, and DATE so that there can be duplicate NAME+COUNTRY rows.
--> I don't want to show the actual NAME values, nor the actual COUNTRY values - just their count and only for those that have visited more than 1 country.
It would be a list like this:
| 9 | 2 | meaning 9 people have visited 2 countries,
| 4 | 3 | meaning 4 people have visited 3 countries,
| 2 | 4 | meaning 2 people have visited 4 countries,
etc.
I'm quite bad at SQL but I guess I need to build some kind of nested query:
select count(t1.NAME)
from TRAVELS t1
where (
select count(distinct COUNTRY)
from TRAVELS t2
where t1.name = t2.name
and count(t2.COUNTRY) > 1
)
Obviously this doesn't work, but I hope it shows my general intention. I haven't been able to find anything about this kind of nested double-count, although it's probably simple enough once I see it?

Try it here: http://sqlfiddle.com/#!2/b0762/3
The query:
select
count(*) as people,
countries_visited
from (
select
name,
count(distinct country) as countries_visited
from travels
group by name
having count(distinct country) > 1
) s
group by countries_visited
order by people desc, countries_visited desc

select country_count, count(*) as people_count
from (select name, count(distinct country) as country_count
from travels
group by name
having count(distinct country) > 1)
group by country_count
of course this assumes that name is unique. If not you may want to user the user_id in place of name.

Related

Select Min and Max value

I have a table called 'customers':
id | name | age
1 | john | 35
2 | paul | 22
3 | ana | 26
4 | mark | 19
5 | jack | 29
i want to select the name and max age, the name and min age... something like:
john 35 mark 19
is it possible?
The below query will give you the min and max on one row as requested. If there are multiple matches for min/max you will get multiple rows. Depending on the SQL engine you use, the syntax to limit to one row is different.
SELECT cMax.Name, cMax.Age, cMin.Name, cMin.Age
FROM customers cMin
JOIN customers cMax ON
cMax.Age = (SELECT MAX(Age) FROM customers)
WHERE cMin.Age = (SELECT MIN(Age) FROM customers)
There are different types of joins (e.g. INNER, OUTER, CROSS); however, for your question it doesn't much matter which you use.
Yes, you can do it,
select name, age from customers
where age in (select max(age)
from customers union select min (age)from customers)
try this
select name, age from customers where age=(select max(age) from customers) union
select name, age from customers where age=(select min(age) from customers)
If you want them on the same row:
select cmin.*, cmax.*
from (select name, age as minage
from customers
order by age asc
fetch first 1 row only
) cmin cross join
(select name, age as maxage
from customers
order by age desc
fetch first 1 row only
) cmax;
fetch first 1 row only is standard syntax for returning only the first row of the result set. Some databases have bespoke syntax, such as limit or select top (1).
Try using this query to show MAX age:-
select * from customers where age=(select max(age) from customers);
To show MIN age use the below Query:-
select * from customers where age=(select min(age) from customers);
You could use a cross join, which will put the two query ouputs next to one another. Building off Rodrigo's queries:
select
max_cust.name,
max_cust.age,
min_cust.name,
min_cust.age
from (select name, age from customers where age=(select max(age) from customers)) as max_cust
cross join (select name, age from customers where age=(select min(age) from customers)) as min_cust
It's maybe not the most performant but it gets the right shape. Be wary of cross joins when the tables don't have exactly 1 row, as it creates a cartesian product of the rows in the tables being joined.

SQL select attribute tupel in reversed order (not order by)

I have a mysql table with entries of my driver's logbook. In the table there are two columns: start_place and end_place. Sometimes it's possible, that end_place is equal to start_place (i think that sounds logical).
Now I wan't to select the entries of the table which occour as tupel (x,y), but not as (y,x).
Example:
id | start_place | end_place
-----------------------------------
0 | New York | San Francisco
-----------------------------------
1 | San Francisco | New York
The row with the id 1 is a duplicate of id 0 in reversed order and should not be part of the result.
Does someone has an idea? Several times I tried with subselects or where conditions like (x,y) != (y,x) but that doesn't work.
This can be done with least and greatest functions with a group by.
select least(start_place,end_place), greatest(start_place,end_place)
from tbl
group by least(start_place,end_place), greatest(start_place,end_place)
having count(*) = 1
To retrieve such rows with other columns, use
select *
from tbl
where (least(start_place,end_place), greatest(start_place,end_place))
in (select least(start_place,end_place), greatest(start_place,end_place)
from tbl
group by least(start_place,end_place), greatest(start_place,end_place)
having count(*) = 1
)
Use LEAST, GREATEST and DISTINCT to get distinct pairs:
select distinct
least(start_place, end_place) as place1,
greatest(start_place, end_place) as place2
from mytable;

Guidance required for sql query

I have a database with one table as shown below. Here I'm trying to write a query to display the names of medication manufactured by the company that manufactures the most number of medications.
By looking at the table we could say the medication names which belongs to the company id 1 and 2 - because those company manufactures the most medication according to this table, but I'm not sure how to write a query for selecting the same i said before.
ID | COMPANY_ID | MEDICATION_NAME
1 1 ASPIRIN
2 1 GLUCERNA
3 2 SIBUTRAMINE
4 1 IBUPROFEN
5 2 VENOFER
6 2 AVONEN
7 4 ACETAMINOPHEN
8 3 ACETAMINO
9 3 GLIPIZIDE
Please share your suggestions. Thanks!
Several ways to do this. Here's one which first uses a subquery to get the maximum count, then another subquery to get the companies with that count, and finally the outer query to return the results:
select *
from yourtable
where companyid in (
select companyid
from yourtable
group by companyid
having count(1) = (
select count(1) cnt
from yourtable
group by companyid
order by 1 desc
limit 1
)
)
SQL Fiddle Demo
This Query might work. I have not tested but the logic is correct
SELECT MEDICATION_NAME
FROM TABLE where
COMPANY_ID=(SELECT
MAX(counted)
FROM ( SELECT COUNT(*) AS counted FROM TABLE ) AS counts);

How can I select the first time a number shows up in more than one column in MySQL?

I have a table of flights, which have an origin and destination city, represented as a foreign id.
A very simplified example of this table looks like:
id | origin | destination
023 1 3
044 3 2
332 2 1
509 1 3
493 1 4
I need to get the first time that a city shows up as an origin or a destination; a list of all the flights that contain a city that hasn't been flown to or from yet.
What I would like to get for the above example would be:
023: 1, 3
044: 2
493: 4
Flights 332 and 509 aren't in the output because they only visit cities that have already been visited.
Here's what I've tried:
(SELECT distinct(origin), distinct(destination) FROM flights ORDER BY id)
Doesn't work because you can't select more than one distinct column
SELECT (distinct(origin) FROM flights ORDER BY id) UNION (distinct (destination) FROM flights ORDER BY id)
Doesn't work because of syntax errors, but mainly because it doesn't take into account that a city should be unique in the origin and destination columns.
If there's not a quick way to do this in SQL I'm also happy to just iterate through and keep track of cities that have been visited (this app has literally one user, and he doesn't care about a few milliseconds of computation because he's over 80), but I'd love to know just so that I can learn more about SQL!
This does it:
SELECT id, GROUP_CONCAT(city ORDER BY city) cities
FROM (
SELECT city, min(id) id
FROM (
SELECT origin city, MIN(id) id
FROM flights
GROUP BY city
UNION
SELECT destination city, MIN(id) id
FROM flights
GROUP BY city) u
GROUP BY city) x
GROUP BY id
DEMO

MS SQL double group by

I have a table 'Hobbys' with two columns. It looks like this:
NAME | HOBBY
Alice | sport
Bob | painting
... | ...
Yves | programming
Zooey | theatre
Rows could be duplicated. For example 'Bob' with hobby 'painting' can appear twice, thrice or even more times.
I want find that people, who have more than one hobby. I tried to use query like this one:
select NAME, HOBBY
from Hobbys
group by NAME, HOBBY
order by 1, 2
But I don't know how to use the query result for second grouping by NAME.
To find the users with more than one hobby, just group by the name and count the distinct hobbies;
SELECT name
FROM hobbies
GROUP BY name
HAVING COUNT(DISTINCT hobby)>1
An SQLfiddle to test with.
If you want the users and their hobbies, you can use a CTE;
WITH cte AS (
SELECT name FROM hobbies GROUP BY name HAVING COUNT(DISTINCT hobby)>1
)
SELECT * FROM hobbies JOIN cte ON hobbies.name = cte.name
Another SQLfiddle.
I want find that people, who have more than one hobby.
In my opinion the easiest is using EXISTS
SELECT NAME,HOBBY FROM dbo.Hobbys h1
WHERE EXISTS
(
SELECT 1 FROM dbo.Hobbys h2
WHERE h1.Name = h2.Name AND h1.HOBBY <> h2.HOBBY
)
Try this..
SELECT NAME,HOBBY
FROM Hobbys
GROUP BY NAME
HAVING COUNT(HOBBY) > 1