I need to print every city from table which has at least one student in every generation. Table is simple but I don't know how to extract every year from that table, because its string.
indeks | city
1/2018 | London ;
2/2018 | Paris ;
3/2018 | null;
4/2019 | London ;
4/2020 | London;
In this case SQL query needs print London, because every year from table has one student (2018,2019 and 2020). I have no idea how to even start query :}
I'd try something like that:
select city from
(
select
city, count(distinct cast(SUBSTRING(indeks, LOCATE('/', indeks)+1) as unsigned)) as dy
from cities
group by city
) as t
where
dy = (
select
max(cast(SUBSTRING(indeks, LOCATE('/', indeks)+1) as unsigned))-min(cast(SUBSTRING(indeks, LOCATE('/', indeks)+1) as unsigned))+1
from cities
)
so in inner query it will calculate how many different years are filled for the each city
outer filter will check which one has all of them
Related
So there is a question I have not been able to find an answer to. Say you want to print each row in a table like the following:
ID | Name | Location
----+------+----------
1 | Adam | New York
2 | Eva | London
3 | Jon | New York
which would give the result
1 Adam New York
2 Eva London
3 Jon New York
Say that I at the same time would like to count the number of occurrences someone lives in a specific city, and save that value for printing after I've iterated through the table; is that possible? For example, printing the following:
1 Adam New York
2 Eva London
3 Jon New York
Inhabitants in New York: 2
Inhabitants in London: 1
Is this possible or would you have to iterate through the entire table twice by grouping by Location the second time, and counting those?
EDIT:
To clarify, I know I can solve it by calling:
SELECT * FROM table;
SELECT CONCAT('Inhabitants in ', Location, ': ', COUNT(ID))
FROM table
GROUP BY Location;
But now I am iterating through it twice. Is it possible to do it in only one iteration?
Generally speaking, yes, displaying every row from the table and displaying aggregated data is two separate tasks which should be handled by application, not by the database.
You have the option to run two queries - a plain select * from T, and select location, count(*) from T group by location, and displaying results sequentially. You also have the option to run only a select * from T one, and count the rows within your application, since you're displaying all rows anyway: use any dictionary-like structure your app language provides, with location string for key and running total integer for value.
If you're keen on keeping it a single query, check out WITH ROLLUP clause - https://dev.mysql.com/doc/refman/8.0/en/group-by-modifiers.html. This would certainly be an unusual way of using it, but if you group by location, id and then tamper with results a little, you can get what you want.
select if(id is null, CONCAT('Inhabitants in ', location, ': ', cnt), concat(id, ' ', name, ' ', location))
from
(
select id, location, name, count(*) cnt
from t
where location is not null
group by location, id with rollup
) q
where location is not null
order by id is null, id asc;
Though the performance could be questionable, compared to two plain queries; you should experiment or check with EXPLAIN.
Try below query, use subquery
select concat(concat(concat('Inhabitants in ',location),':'),total)
from
(select location, count(id) total
from tablename group by location)a
table 1: employee
name| mobile| location
alex| 123 | australia
john| 456 | paris
kohl| 678 | australia
table 2:employment
id|location |data
1 |australia|[{"name":"alex","mobile":"123"},{"name":"kohl","mobile":"678"}]
2 |paris |[{"name":"john","mobile":"456"}]
i have two tables named "employee" and "employment". How can i get all the column values of employee table into one column of employment table as shown in table 2. I am new to SQL querying. I honestly don't have any idea on how to proceed. Any pointers and suggestions are appreciated.
You can use the following solution using CONCAT and GROUP_CONCAT to get this result:
SELECT location, CONCAT("[", GROUP_CONCAT(CONCAT('{"name":"', name, '","mobile":"', mobile, '"}')), "]") AS data
FROM employee
GROUP BY location
demo: http://sqlfiddle.com/#!9/ab25ee/2/0
To JOIN the employee table with the employment you can use the following solution:
SELECT employment.id, employment.location, CONCAT("[", GROUP_CONCAT(CONCAT('{"name":"', name, '","mobile":"', mobile, '"}')), "]") AS data
FROM employment INNER JOIN employee ON employment.location = employee.location
GROUP BY id, location
demo: http://sqlfiddle.com/#!9/12f9c9/1/0
I am quite new to mySQL and need help.
I have a database like this (values are example):
name |region |population|
----------------------------------
Cuba |Carribean |10 |
Ukraine|Eastern Europe|15 |
Belarus|Eastern Europe|9 |
Haiti |Carribean |3 |
I want to find total population of the region (e.g. all population from Eastern Europe) and print as a table the region name and its total population.
But I have no idea how to find a sum of field value from one column but under condition from another column.
How to to do this query?
SELECT region, SUM(population) AS population
FROM table
GROUP BY region
Try below query:
select name , region , sum(population)
from region_table // table_name
group by name , region
May be this will help you.
I need to query two tables like this...
table one
customers
id companyname phone
1 | microsoft | 888-888-8888
2 | yahoo | 588-555-8874
3 | google | 225-558-4421
etc...
table two
contacts
id companyid name phone
1 | 1 | sam | 558-998-5541
2 | 1 | john | 558-998-1154
3 | 3 | larry | 111-145-7885
4 | 3 | dave | 558-998-5254
5 | 2 | sam | 558-997-5421
I need to query both tables.
So if I search for sam
it should return a list of companies with the contacts
microsoft 888-888-8888
sam 558-998-5541
john 558-998-1154
yahoo 588-555-8874
sam 558-997-5421
so it returns all company with sam and all contacts with it....
same is if I would search 'microsoft' it should return without yahoo
microsoft 888-888-8888
sam 558-998-5541
john 558-998-1154
and if I search "558-998-1154" it should return like this...
microsoft 888-888-8888
sam 558-998-5541
john 558-998-1154
I hope this is clear....
Here is my current query:
SELECT * FROM
customers, customer_contacts
WHERE (customers.code LIKE '%#URL.qm1#%'
or customers.COMPANY LIKE '%#URL.qm1#%'
or customers.phone LIKE '%#URL.qm1#%'
or customers.contact LIKE '%#URL.qm1#%'
or customers.name LIKE '%#URL.qm1#%'
or customers.address1 LIKE '%#URL.qm1#%')
AND (customers.id = customer_contacts.cid
and customer_contacts.deleted = 0)
this returns only those who have a contact...
I would need
it to return the ones without contacts as well.
This is a sticky problem, one that I almost want to say "don't try to do this is one query".
I approach SQL queries like this from a programming perspective, as I feel the results tend to be less "magical". (A property I see in too many queries — it seems SQL queries these days are written using monkeys at keyboards…)
Figure out which company IDs we want to list. This is the union of these two things:
Any "people" results matched on name or number
Any "company" results matched on name or number
List out the number for that company, and the people as well.
Let's do #2 first:
SELECT
companyname AS name,
phone
FROM
customers
WHERE id IN (company_ids we want)
UNION
SELECT
name, phone
FROM
contacts
WHERE companyid IN (company_ids we want)
Since "company_ids we want" is going to be a query, rearrange this to boil it down to just 1 occurrence:
SELECT
name, phone
FROM
(
SELECT
id AS companyid,
companyname AS name,
phone
FROM
customers
UNION
SELECT companyid, name, phone FROM contacts
) AS entities
WHERE
companyid IN (company_ids we want)
Now, to fill in the fun part, we need to answer #1:
Part #1.1 is:
SELECT companyid FROM contacts WHERE name = $search OR number = $search;
Part #1.2 is:
SELECT id AS companyid FROM customers WHERE companyname = $search OR number = $search;
(Note that $search is our input — parameterized queries differ greatly from one SQL vendor to the next, so replace that syntax as needed.)
Put the UNION of those two in the IN, and we're done:
SELECT
name, phone
FROM
(
SELECT
id AS companyid,
companyname AS name,
phone
FROM
customers
UNION
SELECT companyid, name, phone FROM contacts
) AS entities
WHERE
companyid IN (
SELECT companyid FROM contacts WHERE name = $search OR phone = $search
UNION
SELECT id AS companyid FROM customers WHERE companyname = $search OR phone = $search
)
;
And pray the database can figure out a query plan that performs this in a reasonable amount of time. Sure you don't want to roundtrip to the DB a few times?
Note the methodology: We determined what we wanted ("the names/phones for customers/contacts matching certain companyids") and then figured out the missing piece ("which company ids?"). This comes from the fact that once you match a particular person in a company (say, sam), you want everyone from that company, plus the company, or everything with that company ID. Knowing that, we get our outer query (#2), and then we just need to figure out how to determine which companies we're interested in.
Note that these won't (and SQL queries, without an ORDER BY don't) give the queries back in your rather fancy order. You can add a helper column to the inner query, however, and accomplish this:
SELECT
name, phone
FROM
(
SELECT
0 AS is_person,
id AS companyid,
companyname AS name,
phone
FROM
customers
UNION
SELECT 1 AS is_person, companyid, name, phone FROM contacts
) AS entities
WHERE
companyid IN (
SELECT companyid FROM contacts WHERE name = $search OR phone = $search
UNION
SELECT id AS companyid FROM customers WHERE companyname = $search OR phone = $search
)
ORDER BY
companyid, is_person, name
;
You can also use the is_person column (if you add it to the SELECT) if you need to segment the results in whatever gets this query's results.
(And if you end up using queries of this length, please, for the love of God, -- comment them!)
I have a table that looks like this:
target_id || country_code
5-----------||-------US----
5-----------||-------CA---
2----------||-------FR----
3----------||-------SP----
3----------||-------FR----
And another table that looks like this:
target_id || region_name
5-----------||---North America
2-----------||-----France------
3-----------||-----Some Europe
As you can see, table 2 contains locations and target_ids, while table 1 contains where these locations are targeted. In the case of North America, it is targeted to 5, which belongs to Canada and US. France, on the other hand has a target_id of 2, and Some Europe a target_id of 3, which contains France again and Spain.
What I would like to do via MySQL, is to get a table of target_id, country_code, country_name but only for countries. This means, only to the target_ids of table 1 that are in only one row (for example, we know that FR is a country because number 2 is only in FR, and we know that 3 represents a region because it has both Spain and France associated). Is this possible to do via MySQL or will I need two queries and PHP in the middle?
Thanks!
SELECT t1.target_id, t1.country_code, t2.region_name
FROM table1 t1
JOIN table t2
ON t1.target_id = t2.target_id
WHERE (SELECT COUNT(*) FROM table1 t3 WHERE t3.target_id = t1.target_id) = 1
table1 is the one with the country codes, table2 is the one with the the region names.