php.de

Zurück   php.de > Webentwicklung > Datenbanken

Datenbanken SQL und Co

Antwort
 
LinkBack Themen-Optionen Thema bewerten
Alt 06.12.2009, 10:38  
Erfahrener Benutzer
 
Registriert seit: 21.07.2003
Beiträge: 340
PHP-Kenntnisse:
Fortgeschritten
Simbo
Standard verwandte Tags finden

Hallo zusammen...

Ich hab folgende Tabellen:
posts (ID, post_type, post_status,...)
term_taxonomy (taxonomy_id, taxonomy...)
term_relationships (object_id, taxonomy_id,...)

Also Blog-Artikel in posts, Tags in term_taxonomy und die Beziehungen zwischen Tags und Blog-Artikeln in term_relationships. Ein Blog-Artikel kann mehrere Tags haben.

Ich habe ein Array $_selected_tags_taxonomy_ids, das alle taxonomy_ids der aktuell gewählten Tags enthält.
Ich möchte nun alle verwandten Tags finden, also alle Tags die zusammen mit den gewählten Tags bei Blog-Artikeln verwendet wurden.
Dabei dürfen nur Blog-Artikel beachtet werden, bei denen posts.post_type="post" und posts.post_status="publish" ist und nur Tags bei denen term_taxonomy.taxonomy="post_tag" ist.

Mein bisheriger PHP/MySQL-Code hat folgende Probleme:
  • $_related_posts_ids enthält Posts bei denen einer der ausgewählten Tags verwendet wird, soll aber Posts enthalten bei denen alle der ausgewählten Tags verwendet werden
  • $_related_tags_taxonomy_ids enthält am Ende doppelte Einträge. Das kann ich zwar mit array_unique() säubern, würde das aber lieber per SQL machen.
  • und natürlich möchte ich die beiden SELECTs gerne in einer Abfrage zusammenfassen. Ja, irgendwas mit JOIN oder UNION oder so... aber ich werd absolut nicht schlau aus dem MySQL Manual und ich hab keine Ahnung wie ich das jetzt verbinden soll...

Also ich würde mich sehr über Hilfe freuen...

PHP-Code:
$selected_tags_taxonomy_ids implode(', ',$_selected_tags_taxonomy_ids);
$_related_posts_ids $wpdb->get_col("
    SELECT wposts.ID
    FROM $wpdb->term_relationships wterm_relationships, $wpdb->posts wposts
    WHERE wposts.ID = wterm_relationships.object_id
    AND wposts.post_status = 'publish'
    AND wposts.post_type = 'post'
    AND wterm_relationships.term_taxonomy_id IN ("
.$selected_tags_taxonomy_ids.")
"
);
$_related_tags_taxonomy_ids $wpdb->get_col("
    SELECT wterm_taxonomy.term_taxonomy_id
    FROM $wpdb->term_relationships wterm_relationships, $wpdb->term_taxonomy wterm_taxonomy
    WHERE wterm_taxonomy.taxonomy = 'post_tag'
    AND wterm_taxonomy.term_taxonomy_id = wterm_relationships.term_taxonomy_id
    AND wterm_relationships.object_id IN ("
.implode(', ',$_related_posts_ids).")
    AND wterm_relationships.term_taxonomy_id NOT IN ("
.$selected_tags_taxonomy_ids.")
"
);
$_related_tags_taxonomy_ids array_unique($_related_tags_taxonomy_ids); 
Gruß

Simbo
__________________
simbo.de

Geändert von Simbo (08.12.2009 um 01:05 Uhr).
Simbo ist offline   Mit Zitat antworten
Sponsor Mitteilung
PHP Code Flüsterer

Registriert seit: 21.08.2005
Beiträge: 4682
PHP-Kenntnisse:
Fortgeschritten

Alt 06.12.2009, 23:43  
Erfahrener Benutzer
 
Registriert seit: 21.07.2003
Beiträge: 340
PHP-Kenntnisse:
Fortgeschritten
Simbo
Standard

Schon mal ein Problem weniger: die doppelten Einträge habe ich mit DISTINCT wegbekommen.

Hat bisher niemand eine Idee?
zu kompliziert erklärt?
Problem zu schwer oder gar zu einfach?
__________________
simbo.de

Geändert von Simbo (08.12.2009 um 01:05 Uhr).
Simbo ist offline   Mit Zitat antworten
Alt 07.12.2009, 00:52  
Erfahrener Benutzer
 
Registriert seit: 21.07.2003
Beiträge: 340
PHP-Kenntnisse:
Fortgeschritten
Simbo
Standard

Ich habs jetzt schon mal soweit, dass die beiden Anfragen verknüpft sind... das ist aber bestimmt noch Potenzial hinsichtlich besserer Performance...?

Und ich hab nach wie vor das Problem, wenn ich nach den Verwandten mehrerer Tags (A und B) frage, bekomme ich verwandte Tags zu A und verwandte Tags zu B, will aber nur verwandte Tags zu A und B.

Code:
SELECT DISTINCT
	wterm_taxonomy.taxonomy_id
FROM
	$wpdb->term_taxonomy AS wterm_taxonomy
LEFT JOIN
	$wpdb->term_relationships AS wterm_relationships
ON
	wterm_taxonomy.term_taxonomy_id = wterm_relationships.term_taxonomy_id
WHERE
	wterm_taxonomy.taxonomy = 'post_tag'
AND
	wterm_relationships.object_id IN (
		SELECT DISTINCT
			wposts.ID
		FROM
			$wpdb->posts AS wposts
		LEFT JOIN
			$wpdb->term_relationships AS wterm_relationships
		ON
			wposts.ID = wterm_relationships.object_id
		WHERE
			wterm_relationships.term_taxonomy_id IN (".$selected_tags_taxonomy_ids.")
		AND
			wposts.post_status = 'publish'
		AND
			wposts.post_type = 'post'
	)
__________________
simbo.de

Geändert von Simbo (08.12.2009 um 01:06 Uhr).
Simbo ist offline   Mit Zitat antworten
Alt 07.12.2009, 01:16  
Erfahrener Benutzer
 
Registriert seit: 21.07.2003
Beiträge: 340
PHP-Kenntnisse:
Fortgeschritten
Simbo
Standard

So... nun hab ich ne Lösung... die funktioniert zwar, wie ich das sehe, aber da ich die MySQL Abfrage mit Hilfe eines foreach zusammenbaue, frage ich mich natürlich, ob das nicht auch anders geht... natürlich in Hinsicht auf bessere Performance bei gleichem Ergebnis...

PHP-Code:
$q "
    SELECT DISTINCT
        wterm_taxonomy.taxonomy_id
    FROM
        $wpdb->term_taxonomy AS wterm_taxonomy
    LEFT JOIN
        $wpdb->term_relationships AS wterm_relationships
    ON
        wterm_taxonomy.term_taxonomy_id = wterm_relationships.term_taxonomy_id
    WHERE
        wterm_taxonomy.taxonomy = 'post_tag'
    AND
        wterm_taxonomy.term_taxonomy_id NOT IN ("
.$selected_tags_taxonomy_ids.")
"
;
foreach( 
$_selected_tags_taxonomy_ids as $selected_tag_taxonomy_id ) {
    
$q .= "
    AND
        wterm_relationships.object_id IN (
            SELECT
                wposts.ID
            FROM
                $wpdb->posts AS wposts
            LEFT JOIN
                $wpdb->term_relationships AS wterm_relationships
            ON
                wterm_relationships.term_taxonomy_id  = "
.$selected_tag_taxonomy_id."
            WHERE
                wposts.ID = wterm_relationships.object_id
            AND
                wposts.post_status = 'publish'
            AND
                wposts.post_type = 'post'
        )
    "
;

Würde mich sehr freuen, wenn da mal einer drüberschaun könnte... Danke.
__________________
simbo.de

Geändert von Simbo (08.12.2009 um 01:06 Uhr).
Simbo ist offline   Mit Zitat antworten
Alt 07.12.2009, 01:29  
moderatives Dielektrikum
 
Benutzerbild von nikosch
 
Registriert seit: 21.05.2008
Beiträge: 35.987
PHP-Kenntnisse:
Fortgeschritten
nikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunft
Standard

Das sieht übel aus. Da wird doch ne Megaquery draus! IMHO bestimmt doch nur das IN() die OR-Logik.
__________________
--
One pixel is still too big. Please make it smaller. ASAP.

Initiative Mittelstand.
Die wichtigste Gestaltungsregel im Screendesign ist Pi mal Daumen des Arbeitgebers.
--
nikosch ist offline   Mit Zitat antworten
Alt 07.12.2009, 01:54  
Erfahrener Benutzer
 
Registriert seit: 21.07.2003
Beiträge: 340
PHP-Kenntnisse:
Fortgeschritten
Simbo
Standard

Ja, das siehst du richtig... genau das ist ja das problem...

aber wie sag ich jetzt "gib mir alle object_id, die jedes (!) element in $_selected_tags_taxonomy_ids in term_taxonomy_id haben"...?
__________________
simbo.de

Geändert von Simbo (08.12.2009 um 01:06 Uhr).
Simbo ist offline   Mit Zitat antworten
Alt 07.12.2009, 11:28  
Erfahrener Benutzer
 
Registriert seit: 21.12.2004
Beiträge: 5.233
PHP-Kenntnisse:
Fortgeschritten
mepeisen ist ein wunderbarer Anblickmepeisen ist ein wunderbarer Anblickmepeisen ist ein wunderbarer Anblickmepeisen ist ein wunderbarer Anblickmepeisen ist ein wunderbarer Anblickmepeisen ist ein wunderbarer Anblickmepeisen ist ein wunderbarer Anblick
mepeisen eine Nachricht über ICQ schicken mepeisen eine Nachricht über Skype™ schicken
Standard

Warum baust du das foreach nicht soweit um, dass es ein "wterm_relationships.term_taxonomy_id IN ...." baut?
__________________
www.php-maven.org PHP und Maven vereint: Build/Deploy/Produktion/Konfiguration, Projekt Management, CI, PHPUnit, zahlreiche Frameworks
Twitter @ https://twitter.com/#!/mepeisen und Facebook @ http://t.co/DZnKSUih
mepeisen ist offline   Mit Zitat antworten
Alt 07.12.2009, 12:00  
Erfahrener Benutzer
 
Registriert seit: 21.07.2003
Beiträge: 340
PHP-Kenntnisse:
Fortgeschritten
Simbo
Standard

Ich hab vorhin folgende sehr aufschlussreiche Seite gefunden, die sich ebenfalls mit dem Problem beschäftigt:
TagSchema - Common Data Access Patterns - Items Having All of A Set of Tags

Nun habe ich folgende Query um alle Posts zu erhalten, bei denen alle Tags im Array verwendet wurden:

Code:
SELECT
	wposts.ID
FROM
	".$wpdb->posts." AS wposts
INNER JOIN
	".$wpdb->term_relationships." AS wterm_relationships
ON
	wposts.ID = wterm_relationships.object_id
WHERE
	wterm_relationships.term_taxonomy_id IN (".$selected_tags_taxonomy_ids.")
AND
	wposts.post_status = 'publish'
AND
	wposts.post_type = 'post'
GROUP BY
	wterm_relationships.object_id
HAVING
	COUNT(DISTINCT wterm_relationships.term_taxonomy_id) = ".$selected_tags_taxonomy_ids_count.";
Funktioniert prima.

Wenn ich jetzt aber verwandten Tags haben will, indem ich die beiden SELECTs wieder verknüpfe funktioniert das nicht:

Code:
SELECT DISTINCT
	wterm_taxonomy.term_taxonomy_id
FROM
	$wpdb->term_taxonomy AS wterm_taxonomy
JOIN
	$wpdb->term_relationships AS wterm_relationships
ON
	wterm_taxonomy.term_taxonomy_id = wterm_relationships.term_taxonomy_id
WHERE
	wterm_taxonomy.taxonomy = 'post_tag'
AND
	wterm_taxonomy.term_taxonomy_id NOT IN (".$selected_tags_taxonomy_ids.")
AND
	wterm_relationships.object_id IN (
		SELECT
			wposts.ID
		FROM
			".$wpdb->posts." AS wposts
		INNER JOIN
			".$wpdb->term_relationships." AS wterm_relationships
		ON
			wposts.ID = wterm_relationships.object_id
		WHERE
			wterm_relationships.term_taxonomy_id IN (".$selected_tags_taxonomy_ids.")
		AND
			wposts.post_status = 'publish'
		AND
			wposts.post_type = 'post'
		GROUP BY
			wterm_relationships.object_id
		HAVING
			COUNT(DISTINCT wterm_relationships.term_taxonomy_id) = ".$selected_tags_taxonomy_ids_count.";
	)
Andererseits, wenn ich das ganze in 2 Queries packe und über PHP verknüpfe, funktioniert es:

PHP-Code:
                $query "
                    SELECT
                        wposts.ID
                    FROM
                        "
.$wpdb->posts." AS wposts
                    INNER JOIN
                        "
.$wpdb->term_relationships." AS wterm_relationships
                    ON
                        wposts.ID = wterm_relationships.object_id
                    WHERE
                        wterm_relationships.term_taxonomy_id IN ("
.$selected_tags_taxonomy_ids.")
                    AND
                        wposts.post_status = 'publish'
                    AND
                        wposts.post_type = 'post'
                    GROUP BY
                        wterm_relationships.object_id
                    HAVING
                        COUNT(DISTINCT wterm_relationships.term_taxonomy_id) = "
.$selected_tags_taxonomy_ids_count.";
                "
;
                
$_related_posts_ids $wpdb->get_col($query);
                
$related_posts_ids implode(',',$_related_posts_ids);
                
$query "
                    SELECT DISTINCT
                        wterm_taxonomy.term_taxonomy_id
                    FROM
                        $wpdb->term_taxonomy AS wterm_taxonomy
                    JOIN
                        $wpdb->term_relationships AS wterm_relationships
                    ON
                        wterm_taxonomy.term_taxonomy_id = wterm_relationships.term_taxonomy_id
                    WHERE
                        wterm_taxonomy.taxonomy = 'post_tag'
                    AND
                        wterm_taxonomy.term_taxonomy_id NOT IN ("
.$selected_tags_taxonomy_ids.")
                    AND
                        wterm_relationships.object_id IN ("
.$related_posts_ids.")
                "
;
                
$_related_tags_taxonomy_ids $wpdb->get_col($query); 
Also... kann man das irgendwie in MySQL zusammenfassen?
oder vielleicht sonst noch irgendwie verbessern?
__________________
simbo.de

Geändert von Simbo (08.12.2009 um 01:06 Uhr).
Simbo ist offline   Mit Zitat antworten
Alt 07.12.2009, 12:29  
Erfahrener Benutzer
 
Registriert seit: 21.07.2003
Beiträge: 340
PHP-Kenntnisse:
Fortgeschritten
Simbo
Standard

Ok, das Verknüpfen der beiden SELECTs hat nicht geklappt, weil sich da ein Semikolon eingeschlichen hatte... *hust*

Folgender Code ist also das Endergebnis, funktioniert tadellos:

PHP-Code:
"
SELECT DISTINCT
    wterm_taxonomy.term_taxonomy_id
FROM
    $wpdb->term_taxonomy AS wterm_taxonomy
JOIN
    $wpdb->term_relationships AS wterm_relationships
ON
    wterm_taxonomy.term_taxonomy_id = wterm_relationships.term_taxonomy_id
WHERE
    wterm_taxonomy.taxonomy = 'post_tag'
AND
    wterm_taxonomy.term_taxonomy_id NOT IN ("
.$selected_tags_taxonomy_ids.")
AND
    wterm_relationships.object_id IN (
        SELECT
            wposts.ID
        FROM
            "
.$wpdb->posts." AS wposts
        INNER JOIN
            "
.$wpdb->term_relationships." AS wterm_relationships
        ON
            wposts.ID = wterm_relationships.object_id
        WHERE
            wterm_relationships.term_taxonomy_id IN ("
.$selected_tags_taxonomy_ids.")
        AND
            wposts.post_status = 'publish'
        AND
            wposts.post_type = 'post'
        GROUP BY
            wterm_relationships.object_id
        HAVING
            COUNT(DISTINCT wterm_relationships.term_taxonomy_id) = "
.$selected_tags_taxonomy_ids_count."
    )

Falls da noch wer Verbesserungsvorschläge hat, nur her damit...
__________________
simbo.de

Geändert von Simbo (08.12.2009 um 01:06 Uhr).
Simbo ist offline   Mit Zitat antworten
Alt 07.12.2009, 12:42  
erc
Erfahrener Benutzer
 
Registriert seit: 02.01.2009
Beiträge: 730
PHP-Kenntnisse:
Fortgeschritten
erc wird schon bald berühmt werden
Standard

PHP-Code:
SELECT DISTINCT
    wterm_taxonomy
.term_taxonomy_id
FROM
    $wpdb
->term_taxonomy AS wterm_taxonomy JOIN
    $wpdb
->term_relationships AS wterm_relationships INNER JOIN
    
(
        
SELECT
            wposts
.ID
        FROM
            
".$wpdb->posts." AS wposts
        INNER JOIN
            
".$wpdb->term_relationships." AS wterm_relationships
        ON
            wposts
.ID wterm_relationships.object_id
        WHERE
            wterm_relationships
.term_taxonomy_id IN (".$selected_tags_taxonomy_ids.")
        AND
            
wposts.post_status 'publish'
        
AND
            
wposts.post_type 'post'
        
GROUP BY
            wterm_relationships
.object_id
        HAVING
            COUNT
(DISTINCT wterm_relationships.term_taxonomy_id) = ".$selected_tags_taxonomy_ids_count."
    
) AS temp ON (wterm_relationships.object_id temp.ID)
ON
    wterm_taxonomy
.term_taxonomy_id wterm_relationships.term_taxonomy_id
WHERE
    wterm_taxonomy
.taxonomy 'post_tag'
AND
    
wterm_taxonomy.term_taxonomy_id NOT IN (".$selected_tags_taxonomy_ids."
ist effizienter...
erc ist offline   Mit Zitat antworten
Antwort


Themen-Optionen
Thema bewerten
Thema bewerten:

Forumregeln
Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are an
Gehe zu

Ähnliche Themen
Thema Autor Forum Antworten Letzter Beitrag
Logikproblem tags aha! Datenbanken 3 03.10.2009 19:16
seltsames Problem mit strip_tags und zugelassenen HTML Tags litterauspirna PHP Tipps 2009 9 07.08.2009 14:29
Dynamische Meta Tags für SEO sdvs PHP Tipps 2009 6 17.06.2009 15:43
[Erledigt] str_replace aber ohne tags, welche danach wieder vorhanden sind? Promaetheus PHP Tipps 2009 19 01.06.2009 21:27
[Erledigt] HTML tags verbieten spikytux PHP Tipps 2009 6 07.02.2009 13:48
OT Diskussion [php] Tags Hinweis nikosch Off-Topic Diskussionen 45 22.09.2008 23:12
[Erledigt] RegEx: beliebige HTML Tags in String ersetzen Der Blaue Gott Balmung PHP Tipps 2008 8 13.09.2008 18:01
mysql tags notyyy Datenbanken 4 12.02.2008 08:39
Bestimme HTML Tags mittels RegEx rausfiltern Mano PHP Tipps 2008 6 27.09.2007 14:22
[Erledigt] Regex für alle Tags auf Level 1 Andreas PHP-Fortgeschrittene 4 16.11.2006 07:58
nur erlaubte html tags umwandeln PHP Tipps 2006 2 30.10.2006 13:53
[Erledigt] Umwandeln in HTML-Entities ohne Umwandeln der TAGS PHP-Fortgeschrittene 4 26.12.2005 16:17
[Erledigt] preg_match_all - Tags mit Attributen PHP-Fortgeschrittene 5 13.09.2005 11:57
[Erledigt] Frage: Text abschneiden aber auf html tags achten PHP-Fortgeschrittene 1 19.01.2005 20:46
[Erledigt] imap_qprint ohne (HTML Tags) PHP-Fortgeschrittene 0 29.09.2004 14:09

Besucher kamen über folgende Suchanfragen bei Google auf diese Seite
tags finden, verwandte tags, $wpdb left join, verwandte finden, $wpdb->posts where tag post_type, blog tags finden, verwandte tags mit php, group by object_id having count(object_id) =, php tag finden, taxonomy post_tag, ich möchte einen verwandten finden, datenbank term_relationships, php tag suchen, nach tags suchen php, sql verwandte tags finden, wo kann ich verwandte finden

Alle Zeitangaben in WEZ +2. Es ist jetzt 09:20 Uhr.




Powered by vBulletin® Version 3.7.2 (Deutsch)
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.2.0
Aprilia-Forum, Aquaristik-Forum, Liebeskummer-Forum, Zierfisch-Forum, Geizkragen-Forum