в БД PostgreSQL есть таблица Provider со строками id и name. Также есть таблица Currencies с полями id и currency, и Countries с полями id и country. Между Provider и Currencies, и Provider и Countries связь Many to Many, соответственно есть 2 таблицы ссылок provcurr и provcountries. Каждому провайдеру может соответствовать произвольное количество countries и currencies.
Задача состоит в том, чтобы прочитать из таблицы провайдеров с заданной страной и вернуть в виде списка.
Выглядит это на данный момент как-то так:
private static String SELECT_BY_COUNTRY = "SELECT * " +
" FROM provider " +
" INNER JOIN provcurr" +
" ON provider.id = provcurr.idprov" +
" INNER JOIN provider_curr " +
" ON provider_curr.id = idcurr" +
" INNER JOIN provcountry" +
" ON provider.id = provcountry.idprov" +
" INNER JOIN provider_country" +
" ON provider_country.id = idcountry" +
" WHERE country = ?";
public ArrayList<Provider> select(Country country) {
ArrayList<Provider> result = null;
try {
preparedStatement = connection.prepareStatement(SELECT_BY_COUNTRY);
preparedStatement.setString(1, country.toString());
ResultSet provider = preparedStatement.executeQuery();
result = createProviderList(provider);
System.out.println(result);
System.out.println("All providers was selected from database");
System.out.println("Generating provider's list");
} catch (SQLException e) {
System.err.println("Unable to select providers \n" + e.toString());
} finally {
return result;
}
}
private ArrayList<Provider> createProviderList(ResultSet provider) throws SQLException {
Map<String, Provider> providers = new HashMap<>();
while (provider.next()) {
String providerName = provider.getString("name");
if (!providers.containsKey(providerName)) {
providers.put(providerName, new Provider(providerName, new ArrayList<>(), new ArrayList<>()));
}
if (!providers.get(providerName).containsCurrencsy(provider.getString("currency"))) {
providers.get(providerName).addCurrency(provider.getString("currency"));
}
if (!providers.get(providerName).containsCountry(provider.getString("country"))) {
providers.get(providerName).addCountry(provider.getString("country"));
}
}
System.out.println("List was generated");
return new ArrayList<Provider>(providers.values());
}
Проблема состоит в том, что при таком запросе я получаю в результате только заданную страну. При этом провайдеру может соответствовать далеко не только эта страна.
Собственно вопрос - как одним запросом получить провайдеров, которым соответствует заданная страна со списком всех остальных стран и валют?
Схема таблиц (стрелка от provcurr к provider в другую сторону):
Когда запрос становится сложным и запутанным, значит проблемы со схемой базы данных. Если я правильно понял, то нужно вытащить всю информацию о провайдерах, которые привязаны к определенной стране. Если так то:
CREATE TABLE "provider" (
"id" int NOT NULL,
"name" varchar(25) NOT NULL
);
CREATE TABLE "provcountries" (
"idprov" int NOT NULL,
"idcountry" int NOT NULL
);
CREATE TABLE "provcurr" (
"idprov" int NOT NULL,
"idcurr" int NOT NULL
);
CREATE TABLE "provider_curr" (
"id" int NOT NULL,
"currency" varchar(25) NOT NULL
);
CREATE TABLE "provider_сountry" (
"id" int NULL,
"country" varchar(25) NULL
);
INSERT INTO provider VALUES (1, 'provider1');
INSERT INTO provider VALUES (2, 'provider2');
INSERT INTO provider VALUES (3, 'provider3');
INSERT INTO provider_curr VALUES (1, 'currency1');
INSERT INTO provider_curr VALUES (2, 'currency2');
INSERT INTO provider_curr VALUES (3, 'currency3');
INSERT INTO provider_сountry VALUES (1, 'country1');
INSERT INTO provider_сountry VALUES (2, 'country2');
INSERT INTO provider_сountry VALUES (3, 'country3');
INSERT INTO provcountries VALUES (1, 1);
INSERT INTO provcountries VALUES (1, 2);
INSERT INTO provcountries VALUES (2, 3);
INSERT INTO provcountries VALUES (3, 1);
INSERT INTO provcurr VALUES (1, 1);
INSERT INTO provcurr VALUES (1, 2);
INSERT INTO provcurr VALUES (2, 3);
INSERT INTO provcurr VALUES (3, 2);
SELECT
p.id AS provider_id,
p.name AS provider_name,
cur.idcurr AS currency_id,
cur.currency AS currency_name,
co.idcountry AS country_id,
co.country AS country_name
FROM
( SELECT id, name FROM provider WHERE id IN (SELECT idprov FROM provcountries WHERE idcountry = 1) ) AS p
LEFT JOIN
( SELECT idprov, idcountry, country FROM provcountries pco JOIN provider_сountry co ON (co.id = pco.idcountry)) AS co
ON (p.id = co.idprov)
LEFT JOIN
( SELECT idprov, idcurr, currency FROM provcurr pcr JOIN provider_curr cr ON (cr.id = pcr.idcurr) ) AS cur
ON (p.id = cur.idprov)
Результат:
provider_id;provider_name;currency_id;currency_name;country_id;country_name
1;provider1;1;currency1;2;country2
1;provider1;2;currency2;2;country2
1;provider1;1;currency1;1;country1
1;provider1;2;currency2;1;country1
3;provider3;2;currency2;1;country1
Виртуальный выделенный сервер (VDS) становится отличным выбором
В базе PosgreSQL есть колонка с jsonb, я хочу получить содержимое этой колонки не как строку, а как объект(преобразовать json в объект на лету, чтобы...
Здравствуйте, я начинающий android-разработчикУ меня имеется приложение, которое я хочу адаптировать под различные устройства