dlaczego te dwa podzapytania dają różne wyniki? sqlite java jdbc

0

Mam dwa podzapytania które teoretycznie (zgodnie z moim zamysłem) powinny dawać takie same wyniki, a dają różne:

select ( select order_id 
		from order_items
		where order_items.product_id = products.product_id) as order_id
from products
where 'Heller' = ( select brand_name
				   from brands
				   where brands.brand_id = products.brand_id)
select order_id
from order_items
where product_id IN (select product_id
					from products
					where brand_id IN(select brand_id
					from brands
					where brand_name = 'Heller'))

W pierwszym przypadku znalezionych tabel jest tylko 3, a w drugim blisko 100.

Podzapytania odnoszą się do przykładowej bazy której schemat znajduje się tutaj:
https://www.sqlservertutorial.net/sql-server-sample-database/

Czy z tymi zapytaniami jest coś nie tak, czy może to jakiś problem z biblioteką Javy?

Podzapytania uruchamiam przez taką funkcję:

 public void order_id_subquery_test(){
        String sql = "select ( select order_id \n" +
                "\t\tfrom order_items\n" +
                "\t\twhere order_items.product_id = products.product_id) as order_id\n" +
                "from products\n" +
                "where 'Heller' = ( select brand_name\n" +
                "\t\t\t\t   from brands\n" +
                "\t\t\t\t   where brands.brand_id = products.brand_id)";


        try (Connection conn = this.connect();
             Statement stmt  = conn.createStatement();
             ResultSet rs    = stmt.executeQuery(sql)){

            // loop through the result set
            while (rs.next()) {
                System.out.println(rs.getInt("order_id"));
            }
            System.out.println ( "end" );

        } catch (SQLException e) {
            System.out.println(e.getMessage());
        }
    }
0

Jawoh Herr Obersturmbannführer l ....

Używasz poradnika do MS SQL Servera i bazy SQLite, egzotyczne.
Po drugie Javy i SQLite, Równie egzotyczne połączenie. Nawet nie wiem czy / jaki jest sterownik JDBC (de facto pełny silnik bazy).

SQLite jest jak najdalszy od bycia rzetelną pełnowartościową relacyjną bazą danych, ma tego elementy, ma wyłączenia (i sporo egzotyki). Generalnie przeznaczony jest do przechowywania prostych danych

Użyj którejś ze sprawdzonych wbudowanych baz Javowskich: H2, HSQLDB , Derby (jest wbudowana w Javę JDK jako Java DB). Stabilne, sprawdzone, pełnowartościowe.
Derby idzie nawet w bardzo dużą zgodność z najlepszymi bazami serwerowymi, nieoficjalnie obstawiam, że będą ci się przyjmowały skryptu z kursu.

3

Roznica zasadnicza jest taka, że w pierwszym zapytaniu pobierasz dane z tabeli products, a w drugim z order_items

Na logikę bo nie przeglądałem schematu, w products masz pojedyncze produkty a w pozycjach zamowienia powielone (jeden prdoukt na kilku zamówieniach).

Obstawiam, że z bazą jest ok, nie wiem natomiast co chcesz oiągnąć....

0

Rozumiem, czyli zapytanie:

select ( select order_id 
          from order_items
          where order_items.product_id = products.product_id) as order_id
from products

Zwraca tylko po jednym order_id dla każdej znalezionej wartości products.product_id.

natomiast zapytanie

select order_id
from order_items
where product_id IN (select product_id
                                   from products ....

zwraca wiele order_id dla każdego znalezionego products.product_id.

A osiągnąć chciałem tyle, że najpierw napisałem to drugie podzapytanie (nieskorelowane), i następnie chciałem napisać zapytanie dające taki sam wynik, tylko przy użyciu podzapytań skorelowanych (czyli to pierwsze). Ale teraz widzę, że to nie będzie takie proste.

0
Obersturmbannführer napisał(a):

Rozumiem, czyli zapytanie:

select ( select order_id 
          from order_items
          where order_items.product_id = products.product_id) as order_id
from products

Zwraca tylko po jednym order_id dla każdej znalezionej wartości products.product_id.

Dla każdego wpisu z product, wykona się zapytanie na order_items. Tak na oko, to zapytanie może nagle przestać działać, gdy w ORDER_ITEMS dla jednego produktu, będziesz miał wiele wpisów.

2

Nie znam SQL Lite i nie bardzo wiem co zwraca to zaytanie:

select ( select order_id 
          from order_items
          where order_items.product_id = products.product_id) as order_id
from products

Na logike to piwinno zwrócić tyle rekordów ile jest w products samo podzapytanie jest dla mnie zagadkowe. Zakładając, że masz jeden produkt o id 1 i dwa zamówienia o id 100 i 200 oba na produkt 1, to silniki które znam zwrócily by błąd, że podzapytanie zwróciło więcej niż jeden wiersz, co zwraca sqlite? Albo jakiego id byś się spodziewał, skoro są 2?

Co do drugiego zapytania, to strasznie dużo tych zagnieżdzeń, ale nie da sie wyjść od tabeli products i uzyskać podzapytaniami id zamowień

@yarel jednak się nie wywali, sam jestem zdziwiony: https://dbfiddle.uk/?rdbms=sqlite_3.27&fiddle=9ad826e87a7f79af86c7b13dfd9962e2

0

W takim razie już jest wszystko jasne.

Z tego co mi się wydaje (dokładnie tego nie sprawdzałem), to podzapytanie

select ( select order_id 
          from order_items
          where order_items.product_id = products.product_id) as order_id
from products

zwraca u mnie po prostu pierwszą znalezioną wartość order_id. Reszta zostaje pominięta.

Podobnie skonstruowane podzapytanie mam w jednym przykładzie ze studiów

select distinct (select kraj 
			from zespoly 
			when id = m.gosc) as kraj 
form mecze m
where 'poland'= (select kraj  
			from zespoly 
			where id = m.gospodarz );

z tym, że w przypadku tego podzapytania, wewnętrzny SELECT zawsze zwraca tylko jedną wartość (w danym meczu tylko jedna drużyna może być gościem). I tylko w takim przypadku tak skonstruowane podzapytanie wydaje się mieć sens.

1

Ja nie wiem czy te zadania miały uczyć pisania podzapytań, ale są strasznie nieczytelne, np ten ze studiów zapisany joinem:

select distinct
    kraj 
from 
    mecze m
    inner join zespoly z on z.id = m.gospodarz
where
     'poland'= kraj ;

daje szybsze rozeznanie w tym co jest pobierane i filtrowane

1 użytkowników online, w tym zalogowanych: 0, gości: 1