MySQL Struggling with join / selection criteria - mysql

I am hoping someone will be able to point me in the right direction.
I have a COUNTRY table, containing a primary ID, and country name (e.g. France)
I have a second table PAYMETHODS_COUNTRIES, which contains a primary id, payment method id (e.g. 4) and country id
I am trying to output a list of checkboxes on each payment method, to control which countries (or users in which countries) have access to those local payment methods.
I have the checkbox list working okay, and the processing of the form is also working. The last remaining thing, is to output the list of country checkboxes with selected countries (e.g. this payment method is available in France and Germany) shown as CHECKED.
So what I am trying to do is to output a complete list of all countries
SELECT id, name FROM country ORDER BY id ASC
And then include the PAYMETHODS_COUNTRIES table something like this (not working of course)
SELECT country.id AS countryid,
country.name AS countryname,
paymethods_countries.id AS methodid
FROM country LEFT JOIN `paymethods_countries`
ON country.id = paymethods_countries.country
WHERE paymethods_countries.paymethod = 10
This example query only shows rows that actually have a record in PAYMETHODS_COUNTRIES, not what I am after.
What I was hoping for, is a complete list of country.id + country.name, with a final field (the ID of the PAYMETHODS_COUNTRIES table) - which should be null where there is no link. That way I should be able to check for null or otherwise, and output CHECKED for those rows.
Hopefully that makes sense - or if anyone knows a better way to achieve what I am doing, your thoughts are appreciated.

While the other answer here will produce the desired result, semantically it is more correct to move the condition from the WHERE clause to the ON clause:
SELECT country.id AS countryid,
country.name AS countryname,
paymethods_countries.id AS methodid
FROM country
LEFT JOIN `paymethods_countries`
ON country.id = paymethods_countries.country and paymethods_countries.paymethod = 10
This eliminates the need to add the extra OR condition in the WHERE clause.

It's only coming back with rows that have record in PAYMETHODS_COUNTRIES because of your WHERE clause since you say the paymethod must = 10. Add an OR to let it be null too:
SELECT country.id AS countryid,
country.name AS countryname,
paymethods_countries.id AS methodid
FROM country
LEFT JOIN `paymethods_countries`
ON country.id = paymethods_countries.country
WHERE paymethods_countries.paymethod = 10
OR paymethods_countries.paymethod IS NULL

Related

Retrieve an overview of all countries that have at least one city, how many cities they have. and the average population of these cities

another day and another mysql problem, ive been scratching my head with this question for quite some while now.
My task is through a database called "world" is to retrive and overview of countries with atleast one city, how many cities they have and the average population of these cities. i would also like to sort the average population by using " (AS AverageCityPopulation)" and the number of cities with "(AS NumberOfCities)".
ive just started to learn about join, left join and right join aswell and i am pretty certain that i have to use one of those 3 to complete the task. im still trying to find a helpful way to memorize when to use those 3 (if you have a tip please leave it down below).
anyways, the data should be sorted like this i feel like
countrycode
countryname
First
row
Second
row
cityname
citycountrycode
First
row
Second
row
averagecitypop
numberofcities
First
row
Second
row
of course the data should be displayed sideways but it is a bit hard to make it work in stackoverflow. anyways, i have tried with multiple queries for now, but still havent found the answer. the closest i got to was the entire avg population of a city in Aruba
my current query is:
SELECT
country.name,
country.code,
city.name,
AVG(city.population) AS averageCityPop,
city.countrycode
FROM
world.city
right JOIN
world.country ON city.CountryCode = country.code
where city.CountryCode > 1
again i am relativly new, so any thesis or curriculum is appriciated as answers in this post and answers to my question, if you also know any good youtube channels or forums where its helpful to learn mysql it would be great!
thanks for any helpful answers <3
here are a few screenshots about the two tables im trying to connect
world.city
world.country
Note that the database I use is MySQL sample database - World.
For beginners: both tables have primary keys (for table country, it is 'code', for table city, it is 'id'), so it's enough to use inner joins.
SELECT co.code AS country_code,
co.name AS country_name,
COUNT(*) AS num_cities,
AVG(ci.population) AS avg_city_pop
FROM country co INNER JOIN city ci ON (co.code = ci.countrycode)
GROUP BY co.code;
Or if you want to show the name of each city:
SELECT co.code AS country_code,
co.name AS country_name,
ci.name AS city_name,
COUNT(*) OVER w AS num_cities,
AVG(ci.population) OVER w AS avg_city_pop
FROM country co INNER JOIN city ci ON (co.code = ci.countrycode)
WINDOW w AS (PARTITION BY co.code);

SQL Query sorting rows by duplicate name keeping lowest in result

I've got a table with 11 columns and I want to create a query that removes the rows with duplicate names in the Full Name's column but keeps the row with the lowest value in the Result's column. Currently I have this.
SELECT
MIN(sql363686.Results2014.Result),
sql363686.Results2014.Temp,
sql363686.Results2014.Full Name,
sql363686.Results2014.Province,
sql363686.Results2014.BirthDate,
sql363686.Results2014.Position,
sql363686.Results2014.Location,
sql363686.Results2014.Date
FROM
sql363686.Results2014
WHERE
sql363686.Results2014.Event = '50m Freestyle'
AND sql363686.Results2014.Gender = 'M'
AND sql363686.Results2014.Agegroup = 'Junior'
GROUP BY
sql363686.Results2014.Full Name
ORDER BY
sql363686.Results2014.Result ASC ;
At first glance it seems to work fine and I get all the correct values, but I seem to be getting a different (wrong) value in the Position column then what I have in my database table. All other values seem to be right. Any ideas on what I'm doing wrong?
I'm currently using dbVisualizer connected to a mysql database. Also, my knowledge and experience with sql is the bare mimimum
Use group by and a join:
select r.*
from sql363686.Results2014 r
(select fullname, min(result) as minresult
from sql363686.Results2014 r
group by fullname
) rr
on rr.fullname = r.fullname and rr.minresult = r.minresult;
You have fallen into the trap of the nonstandard MySQL extension to GROUP BY.
(I'm not going to work with all those fully qualified column names; it's unnecessary and verbose.)
I think you're looking for each swimmer's best time in a particular event, and you're trying to pull that from a so-called denormalized table. It looks like your table has these columns.
Result
Temp
FullName
Province
BirthDate
Position
Location
Date
Event
Gender
Agegroup
So, the first step is to locate the best time in each event for each swimmer. To do this we need to make a couple of assumptions.
A person is uniquely identified by FullName, BirthDate, and Gender.
An event is uniquely identified by Event, Gender, Agegroup.
This subquery will get the best time for each swimmer in each event.
SELECT MIN(Result) BestResult,
FullName,BirthDate, Gender,
Event, Agegroup
FROM Results2014
GROUP BY FullName,BirthDate, Gender, Event, Agegroup
This gets you a virtual table with each person's fastest result in each event (using the definitions of person and event mentioned earlier).
Now the challenge is to go find out the circumstances of each person's best time. Those circumstances include Temp, Province, Position, Location, Date. We'll do that with a JOIN between the original table and our virtual table, like this
SELECT resu.Event,
resu.Gender,
resu.Agegroup,
resu.Result,
resu.Temp.
resu.FullName,
resu.Province,
resu.BirthDate,
resu.Position,
resu.Location,
resu.Date
FROM Results2014 resu
JOIN (
SELECT MIN(Result) BestResult,
FullName,BirthDate, Gender,
Event, Agegroup
FROM Results2014
GROUP BY FullName,BirthDate, Gender, Event, Agegroup
) best
ON resu.Result = best.BestResult
AND resu.FullName = best.FullName
AND resu.BirthDate = best.BirthDate
AND resu.Gender = best.Gender
AND resu.Event = best.Event
AND resu.Agegroup = best.Agegroup
ORDER BY resu.Agegroup, resu.Gender, resu.Event, resu.FullName, resu.BirthDate
Do you see how this works? You need an aggregate query that pulls the best times. Then you need to use the column values in that aggregate query in the ON clause to go get the details of the best times from the detail table.
If you want to report on just one event you can include an appropriate WHERE clause right before ORDER BY as follows.
WHERE resu.Event = '50m Freestyle'
AND resu.Gender = 'M'
AND resu.Agegroup = 'Junior'

Using "not in" on WHERE with AND?

I'm trying to get a better understanding of how "not in" works with WHERE in MySQL.
For example:
SELECT * FROM current_mailing_list
WHERE address1 NOT IN
(select address1 from old_mailing_list) AND
city not in (select city from old_mailing_list);
In the above example, the purpose of the query is to list mailing addresses which are new. address1 is a street address such as 1234 N. Main St. The problem happens when 1234 N. Main St occurs in more than one city, which can happen. So I decided to add city to it to make it more unique.
My question is, is this doing what I expect it to do? Meaning, it should find those street addresses (address1) that don't exist in the old_mailing_list AND then make sure they have a different city.
I have done this, just with the address1:
SELECT * FROM current_mailing_list
WHERE address1 NOT IN
(select address1 from old_mailing_list);
and it produced a much larger list (about 10 times the size). So I wanted to add city to this. Or is my logic in the entirely wrong and need another approach?
Your current query will not return new addresses where EITHER their "address1" or "city" appears at all in the old mailing list. I think you want to select cities where they don't both appear together, like so:
SELECT *
FROM current_mailing_list c
WHERE NOT EXISTS
(
SELECT 1
FROM old_mailing_list
WHERE
address1 = c.address1
AND city = c.city
)
Quite literally; select everything from the current mailing list where there is no record in the old mailing list with the same city and address1.
To use NOT IN, you'll want to combine both the city and address in the same clause as MySQL supports this (other RDBMS do not support this method). As others have pointed out, you won't get your desired results using both separately.
Try this if you want to use NOT IN:
SELECT *
FROM current_mailing_list
WHERE (address1,city) NOT IN
(select address1, city from old_mailing_list);
Sample SQL Fiddle Demo
I prefer to use a LEFT JOIN for this personally though and check for NULL:
SELECT c.*
FROM current_mailing_list c
LEFT JOIN old_mailing_list o ON c.address1 = o.address1 AND c.city = o.city
WHERE o.address1 IS NULL
If 1234 N. Main St. is an address for both a city in the old mailing list and a city in the new mailing list, your query will exclude BOTH addresses. Your query is doing exactly what it says it's doing: you will get addresses where both the street address and the city are not in the old mailing list. If either appear for an address in the old mailing list, that address will not be retrieved.

how to make a dynamic query?

I am working on a little searching stuffs, the problem is that I they can choose multiple options and I want my query to be created depending of them.
Please if anybody could help me I will be so glad.
My main table of search is this:
id
name
card_id
phone_numbre
country_id
futurecountry_id
The ID is unique, the name a text, the card_id and phone_number are just ok, I can find them on my table, but the problem is when I need to go to pick up the data to the other tables, specially the country_id goes to a table named "country" where I comprare the id's to check if are the same I bring the name of the country, is the same table where I consult for get the country_id and futurecountry_id and I really have no idea what to do.
Does anybody have any idea?
p.s. Well, maybe I couldn't explain myself very good, my problem is this:
I have a form where you filled it with some data and brings you the personal information and instead the ids of the field origencountry and destinycountry I need the names, for example, if I send origencountry=10 and destinycountry=8 I will do this:
select *
from infotable,countrytable
where infotable.iddestinycountry = countrytable.id and infotable = 10
AND infotable.origencountry = countrytable.id and infotable = 8
The query seems to work fine, but it doesn't output any data.
At my table countries I have for example:
id name
1 usa
2 uk
3 spain
and at info
id name origencountry destinycountry
1 john 1 2
You can user LEFT JOIN or RIGHT JOIN.
For example :
SELECT c.country_id from country as c
LEFT JOIN futurecountry as fc ON c.country_id = fc.futurecountry_id
In this example, you return only results on country with country and futurecountry_id keys
For more informations, you can see here : http://dev.mysql.com/doc/refman/5.0/fr/join.html

MySQL INNER JOIN syntax

Can someone "break down" the syntax here. Please. I need to learn this ASAP.
From my limited experience -
firstname and lastname are columns and list is a table.
count(id)>1 is used to check if there is more than one row with the same...
That's it. I don't know what this does but I need to understand it.
SELECT firstname, lastname, list.address FROM list
INNER JOIN (SELECT address FROM list
GROUP BY address
HAVING count(id) > 1) dup
ON list.address = dup.address
This query will return a list of all names (first and last name), which contain a duplicate address. This part
SELECT address FROM list
GROUP BY address HAVING count(id) > 1
Gets a list of all the addresses that occur more than once in the table, This is then joined back to the table itself, to return all names which have the same address. This should return a list of all the unique address which have more than 1 name associated with them, along with the names that go along with the addresses.