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

zapytanie o zestaw w relacyjnej bazie danych

Nie będę komentował, czy istnieje lepiej dopasowany schemat do tego (jest to całkiem możliwe), ale dla schematu z kolumnami name i item , poniższe zapytanie powinno działać. (składnia mysql)

SELECT k.name
FROM (SELECT DISTINCT name FROM sets) AS k
INNER JOIN sets i1 ON (k.name = i1.name AND i1.item = 1)
INNER JOIN sets i2 ON (k.name = i2.name AND i2.item = 3)
INNER JOIN sets i3 ON (k.name = i3.name AND i3.item = 5)
LEFT JOIN sets ix ON (k.name = ix.name AND ix.item NOT IN (1, 3, 5))
WHERE ix.name IS NULL;

Chodzi o to, że mamy wszystkie ustawione klucze w k , które następnie łączymy z danymi pozycji zestawu w sets raz na każdy element zestawu w zestawie, którego szukamy, w tym przypadku trzy. Każde z trzech sprzężeń wewnętrznych z aliasami tabeli i1 , i2 i i3 odfiltrować wszystkie nazwy zestawów, które nie zawierają elementu szukanego za pomocą tego sprzężenia. Na koniec mamy połączenie lewe z sets z aliasem tabeli ix , który zawiera wszystkie dodatkowe przedmioty w zestawie, czyli każdy przedmiot, którego nie szukaliśmy. ix.name jest NULL w przypadku, gdy nie znaleziono żadnych dodatkowych elementów, co jest dokładnie tym, czego chcemy, stąd WHERE klauzula. Zapytanie zwraca wiersz zawierający klucz zestawu, jeśli zestaw zostanie znaleziony, w przeciwnym razie żadnych wierszy.

Edytuj: Pomysł za odpowiedzią collapsars wydaje się być znacznie lepszy niż mój, więc oto nieco krótsza wersja tego z wyjaśnieniem.

SELECT sets.name
FROM sets
LEFT JOIN (
    SELECT DISTINCT name
    FROM sets
    WHERE item NOT IN (1, 3, 5)
) s1
ON (sets.name = s1.name)
WHERE s1.name IS NULL
GROUP BY sets.name
HAVING COUNT(sets.item) = 3;

Pomysł polega na tym, że podzapytanie s1 wybiera klucze wszystkich zestawów zawierających elementy inne niż te, których szukamy. Tak więc, kiedy wyszliśmy, dołączamy do sets z s1 , s1.name jest NULL gdy zestaw zawiera tylko przedmioty, których szukamy. Następnie grupujemy według klucza zestawu i odfiltrowujemy wszystkie zestawy zawierające niewłaściwą liczbę elementów. Pozostają nam wtedy tylko zestawy, które zawierają tylko szukane przez nas przedmioty i mają odpowiednią długość. Ponieważ zestawy mogą zawierać element tylko raz, może istnieć tylko jeden zestaw spełniający te kryteria i to jest ten, którego szukamy.

Edytuj: Właśnie dotarło do mnie, jak to zrobić bez wykluczenia.

SELECT totals.name
FROM (
    SELECT name, COUNT(*) count
    FROM sets
    GROUP BY name
) totals
INNER JOIN (
    SELECT name, COUNT(*) count
    FROM sets
    WHERE item IN (1, 3, 5)
    GROUP BY name
) matches
ON (totals.name = matches.name)
WHERE totals.count = 3 AND matches.count = 3;

Pierwsze podzapytanie znajduje całkowitą liczbę elementów w każdym zestawie, a drugie — liczbę pasujących elementów w każdym zestawie. Kiedy matches.count wynosi 3, zestaw zawiera wszystkie elementy, których szukamy, a jeśli totals.count ma również 3, zestaw nie zawiera żadnych dodatkowych elementów.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Proste próbki losowe z bazy danych Sql

  2. Jak utworzyć bezpieczną kwerendę do wykonywania zbiorczego wstawiania w MySQL przy użyciu MySQLCommand w C# bez użycia przechowywanej procedury?

  3. mysql znajdź najmniejszy + unikalny identyfikator dostępny

  4. Lista wyszukiwania CakePHP z powiązanymi warunkami modelu

  5. MySQL CAST jako DATE