Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Jak zwrócić zestaw wyników na podstawie innych wierszy

Oto dwa różne rozwiązania:(Uwaga:nazwałem pole wyliczenia "package_type")

Pierwsze rozwiązanie (za pomocą funkcji IF()):

select 
  i.location, 
  if(ps.id is not null, ps.id, pg.id) as package_id
from 
  (select distinct location from Items) i
  inner join 
    (select i.location, p.id
     from Items i
       inner join Packages p on (i.package_id = p.id and p.package_type = 'general')
    ) pg on (i.location = pg.location)
  left join 
    (select i.location, p.id
     from Items i
       inner join Packages p on (i.package_id = p.id and p.package_type = 'special')
    ) ps on (i.location = ps.location)

To rozwiązanie zasadniczo pobiera lokalizacje i łączy je z pakietem z parametrem ogólnym (który zakłada się, że istnieje; stąd inner join ) i specjalny pakiet (który jest opcjonalny; stąd left join ). Tworzy rekordy takie jak:

location | general-package | [special-package]

Następnie używa MySQL IF funkcja, aby najpierw spróbować wybrać identyfikator pakietu specjalnego, a następnie wrócić do identyfikatora pakietu ogólnego.

Drugie rozwiązanie (poprzez rzutowanie liczby enum na liczbę całkowitą):

select i.location, p.id
from
  (select i.location, max(cast(package_type as unsigned)) as package_type
   from Items i
     left join Packages p on (i.package_id = p.id)
   group by location
  ) i
  inner join 
    (select i.location, p.id, p.package_type
     from Items i
       inner join Packages p on (i.package_id = p.id)
    ) p on (i.location = p.location and i.package_type = p.package_type)

To rozwiązanie wykorzystuje fakt, że wyliczenia są przechowywane jako liczby całkowite. Rzuca wyliczenie na liczbę całkowitą. special w tym przypadku zwróci 2 i general zwróci 1 . Ponieważ gwarantujemy, że te specjalne są w tym przypadku wyższe niż ogólne (tj. 2> 1), możemy użyć MAX funkcja agregująca. Teraz zasadniczo mamy tabelę lokalizacji i ich "zalecanego pakietu" (tj. Specjalnego, jeśli istnieje, ogólnego w przeciwnym razie). Po prostu łączymy to z normalnym zapytaniem wraz z oczekiwanym typem pakietu i zwracamy poprawne wyniki.

Zastrzeżenie:nie jestem pewien co do skuteczności którejkolwiek z tych metod, więc warto przetestować to samodzielnie.

Jeśli chcesz przeprojektować tabelę lub zdenormalizować ją pod kątem wydajności, myślę, że ten projekt może być bardziej odpowiedni:

GeneralPackages table
id, name
1, General Package 1

SpecialPackages table
id, name
1, Special Package 1
2, Special Package 2

Items table
id, general_package_id, special_package_id, location
1, 1, NULL, America
2, 1, 2, Europe

Zaletą byłoby łatwiejsze egzekwowanie kilku reguł na poziomie bazy danych:

  • Lokalizacja musi zawsze mieć pakiet ogólny (Items.general_package_id może być zdefiniowany jako NOT NULL)
  • Lokalizacja musi mieć tylko jeden ogólny pakiet (dodanie go w polu zamiast połączenia gwarantuje, że jest tylko jeden określony)
  • Lokalizacja może mieć co najwyżej jeden specjalny pakiet (dodanie go w polu zamiast połączenia gwarantuje, że jest tylko jeden określony)
  • Klucz obcy w Items.general_package_id =GeneralPackages.id gwarantuje, że ta kolumna zawiera tylko prawidłowe pakiety, które są „ogólne”.
  • To samo można zrobić dla special_package_id.

Wadą byłoby to, że prawdopodobnie będziesz musiał używać UNION ALL za każdym razem, gdy używasz jednego ze swoich starych zapytań.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak sortować wiadomości hakerskie

  2. MySQL 5.6.10 InnoDB nie może utworzyć tabeli, ponieważ tabela już istnieje

  3. Jak wybrać dane, w których pole ma wartość minimalną w MySQL?

  4. Czy to najlepsze podejście do tworzenia ścieżki audytu?

  5. Jak zamówić 1,2,3 a nie 1, 10, 11, 12 w mySQL?