Przecięcie w MySQL


Mam dwie tabele, rekordy i dane. rekordy mają wiele pól (imię, nazwisko itp.). Każde z tych pól jest obcym kluczem do tabeli danych, która przechowuje rzeczywistą wartość. Muszę przeszukiwać wiele pól rekordów.
Poniżej znajduje się przykładowe zapytanie używające INTERSECT, ale potrzebuję takiego, które działa w MySQL.
SELECT records.id FROM records, data WHERE data.id = records.firstname AND data.value = "john"
INTERSECT
SELECT records.id FROM records, data WHERE data.id = records.lastname AND data.value = "smith"

Dzięki za wszelką pomoc.
Zaproszony:
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Możesz użyć sprzężenia wewnętrznego, aby odfiltrować wiersze, które mają pasujący wiersz w innej tabeli:
SELECT DISTINCT records.id 
FROM records
INNER JOIN data d1 on d1.id = records.firstname AND data.value = "john"
INNER JOIN data d2 on d2.id = records.lastname AND data.value = "smith"

Jedną z wielu innych alternatyw jest sugestia
in
:
SELECT DISTINCT records.id 
FROM records
WHERE records.firstname IN ( select id from data where value = 'john') AND records.lastname IN ( select id from data where value = 'smith')
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Myślę, że ta metoda jest znacznie łatwiejsza do naśladowania, ale wiąże się z nią pewien narzut, ponieważ początkowo ładujesz wiele zduplikowanych rekordów. Używam go na bazie danych zawierającej około 10 000-50 000 rekordów i zwykle krzyżuję około 5 zapytań, a wydajność jest akceptowalna.
Wszystko, co robisz, to „UNION ALL” przy każdym zapytaniu, które chcesz przejść, i sprawdzanie, które z nich otrzymasz za każdym razem.
SELECT * From ( (Select data1.* From data1 Inner Join data2 on data1.id=data2.id where data2.something=true)
Union All
(Select data1.* From data1 Inner Join data3 on data1.id=data3.id where data3.something=false)) As tbl GROUP BY tbl.ID HAVING COUNT(*)=2

Tak więc, jeśli otrzymamy ten sam rekord w obu żądaniach, liczba będzie wynosić 2, a końcowe żądanie pakowania będzie to obejmować.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Zamiast tego użyj połączeń:
SELECT records.id
FROM records
JOIN data AS D1 ON records.firstname = D1.id
JOIN data AS D2 ON records.lastname = D2.id
WHERE D1.value = 'john' and D2.value = 'smith'

Oto kilka danych testowych:
CREATE TABLE records (id INT NOT NULL, firstname INT NOT NULL, lastname INT NOT NULL);
INSERT INTO records (id, firstname, lastname) VALUES
(1, 1, 1),
(2, 1, 2),
(3, 2, 1),
(4, 2, 2);CREATE TABLE data (id INT NOT NULL, value NVARCHAR(100) NOT NULL);
INSERT INTO data (id, value) VALUES
(1, 'john'),
(2, 'smith');

Spodziewany wynik:
2

Dane testowe prawdopodobnie nie są przydatne w przypadku plakatu, ale mogą być przydatne dla wyborców, którzy chcą przetestować rozwiązania, aby upewnić się, że działają one poprawnie, lub dla osób, które chcą przesłać odpowiedzi, aby przetestować własne odpowiedzi.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

SELECT t.id FROM table t WHERE NOT EXISTS (SELECT t2.id, FROM table2 t2 WHERE t2.id = t1.id)
https://dev.mysql.com/doc/refm ... .html
https://dev.mysql.com/doc/refm ... .html
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Ogólnym zamiennikiem INTERSECT w MYSQL jest sprzężenie wewnętrzne:
SELECT DISTINCT * FROM 
(SELECT f1, f2, f3... FROM table1 WHERE f1>0)
INNER JOIN
(SELECT f1, f2, f3... FROM table2 WHERE f1>0)
USING(primary_key)

Lub specjalnie dla twojego przypadku:
SELECT DISTINCT * FROM 
(SELECT records.id FROM records, data WHERE data.id = records.firstname AND data.value = "john") query1
INNER JOIN
(SELECT records.id FROM records, data WHERE data.id = records.lastname AND data.value = "smith") query2
USING (id)
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Ponieważ MySQL nie obsługuje INTERSECT, możesz mieć 2 alternatywy:

inner join

i

in
... To jest rozwiązanie z

w

:
SELECT records.id FROM records, data 
WHERE data.id = records.firstname AND data.value = "john"
AND records.id in (SELECT records.id FROM records, data
WHERE data.id = records.lastname AND data.value = "smith);

Aby odpowiedzieć na pytania, Zaloguj się lub Zarejestruj się