igel.daniel
Goto Top

MySQL Abfrage bei m:1 Verbindung

Hallo liebe Community,

ich sitze gerade vor einem SQL-"Problem" - Ich möchte eine Abfrage über mehrere Tabellen machen, wobei diese Tabellen auf eine einzige zugreifen.

Ich habe vier Tabellen mit technischen Spezifikationen von Gerät, Name Soundkarte, Name Grafikkarte, Name Nettzwerkkarte. "Dummerweise" sind die jeweiligen Herstellerbezeichnungen in einer anderen Tabelle gespeichert. Ich habe es bisher nicht geschafft, aller Infos zu einem Gerät - also Gerät + Hersteller, Grafikkarte + Hersteller, ... in einer einzigen SQL Query abzufackeln. Geht das überhaupt?

Herzlichen Dank und beste Grüße

Content-Key: 281312

Url: https://administrator.de/contentid/281312

Printed on: April 18, 2024 at 23:04 o'clock

Mitglied: 122990
122990 Aug 27, 2015 at 07:57:40 (UTC)
Goto Top
Hallo,
SQL Joins ist dein Stichwort ...

Gruß grexit
Member: ukulele-7
ukulele-7 Aug 27, 2015 at 08:02:11 (UTC)
Goto Top
Also wenn ich dich richtig verstehe suchst du das hier:
SELECT	t.name,
		tabelle_hersteller.name
FROM	(

SELECT	tabelle_geraet.name,
		tabelle_geraet.hersteller_id
FROM	tabelle_geraet
UNION ALL
SELECT	tabelle_soundkarten.name,
		tabelle_soundkarten.hersteller_id
FROM	tabelle_soundkarten
UNION ALL
SELECT	tabelle_grafikkarten.name,
		tabelle_grafikkarten.hersteller_id
FROM	tabelle_grafikkarten
UNION ALL
SELECT	tabelle_netzwerkkarten.name,
		tabelle_netzwerkkarten.hersteller_id
FROM	tabelle_netzwerkkarten

		) t
LEFT JOIN tabelle_hersteller ON tabelle_hersteller.id = t.hersteller_id
Member: IGEL.Daniel
IGEL.Daniel Aug 27, 2015 at 08:03:38 (UTC)
Goto Top
Hallo grexit,

soweit war ich auch schon. Aber ich kann ja eine Tabelle nicht mehrmals (left) joinen, oder?

Gruß
Mitglied: 122990
Solution 122990 Aug 27, 2015 updated at 09:17:43 (UTC)
Goto Top
Zitat von @IGEL.Daniel:
soweit war ich auch schon. Aber ich kann ja eine Tabelle nicht mehrmals (left) joinen, oder?
Mit Subqueries oder Aliasen schon ... siehe Ukulele's Post.
Member: IGEL.Daniel
IGEL.Daniel Aug 27, 2015 at 08:13:11 (UTC)
Goto Top
Danke

Dann probiere ich es mal aus => zuerst muss ich mal über das UNION ALL schlau machen
Member: ukulele-7
Solution ukulele-7 Aug 27, 2015 updated at 09:17:26 (UTC)
Goto Top
Du kannst Joinen so oft du willst nur musst du dann mit Tabellen Aliasen arbeiten. Ein Join wird dir die Daten aber immer "nebeneinander" stellen, UNION hängt dir Tabellen "unten an" (bei gleicher Spaltenanzahl und Datentyp). Ich kenne deine Tabellen nicht, vieleicht brauchst du auch einfach nur mehrere Joins und deine Komponenten wie Sound- und Grafikkarte sind mit der Gerätetabelle verknüpft.
Member: IGEL.Daniel
IGEL.Daniel Aug 27, 2015 at 09:17:23 (UTC)
Goto Top
Hallo ukulele,

Dein Ansatz war schon sehr gut, ich habe ein Ergebnis bekommen (wenn ich den Hersteller unten im Code rauslasse)

SELECT
	t.designation, M.name
FROM
	(
	SELECT
        C.manufacturers_id
    FROM 
		glpi_computers AS C
		UNION ALL    
    SELECT
    	DGC.designation, DGC.manufacturers_id
	FROM
 		glpi_devicegraphiccards AS DGC
		UNION ALL
	SELECT
 		DSC.designation, DSC.manufacturers_id
	FROM
 		glpi_devicesoundcards AS DSC
		UNION ALL
    SELECT
    	DNC.designation, DNC.manufacturers_id
	FROM
 		glpi_devicenetworkcards AS DNC
        
 	) t
LEFT JOIN
	glpi_manufacturers AS M
ON
	t.manufacturers_id = M.id

Nur wenn ich den Herstellernamen dazu haben will, knallt es, da ich da nur einen Wert habe - die manufactures_id. SQL wirft mir dann natürlich den Fehler, weil die Spaltenanzahl nicht hinhaut.

Zudem "gefällt" mir die Darstellung nicht - ich bräuchte es für jedes Gerät in einer Reihe, nicht alle Ergebnisse untereinander.

Beste Grüße,
Daniel
Member: ukulele-7
Solution ukulele-7 Aug 27, 2015 updated at 10:28:55 (UTC)
Goto Top
Dein erster Select den du mit UNION ALL verkettest hat auch nur eine Spalte, kann so nicht funktionieren. Also so würde es schonmal funktionieren:
SELECT
	t.designation, M.name
FROM
	(
    SELECT
    	DGC.designation, DGC.manufacturers_id
	FROM
 		glpi_devicegraphiccards AS DGC
		UNION ALL
	SELECT
 		DSC.designation, DSC.manufacturers_id
	FROM
 		glpi_devicesoundcards AS DSC
		UNION ALL
    SELECT
    	DNC.designation, DNC.manufacturers_id
	FROM
 		glpi_devicenetworkcards AS DNC
        
 	) t
LEFT JOIN
	glpi_manufacturers AS M
ON
	t.manufacturers_id = M.id
Wenn du aber sowieso schreibst " ich bräuchte es für jedes Gerät in einer Reihe" dann hast du vermutlich eine ganz andere Struktur und suchst eher das hier:
SELECT	C.name,
MC.name,
		DGC.designation,
		MDGC.name,
		DSC.designation,
		MDSC.name
FROM	glpi_computers C
LEFT JOIN glpi_manufacturers MC ON MC.id = C.manufacturers_id
LEFT JOIN glpi_devicegraphiccards DGC ON DGC.id = C.graphiccard_id
LEFT JOIN glpi_manufacturers MDGC ON MDGC.id = DGC.manufacturers_id
LEFT JOIN glpi_devicesoundcards DSC ON DSC.id = C.soundcard_id
LEFT JOIN glpi_manufacturers MDSC ON MDSC.id = DGC.manufacturers_id
usw.
Member: IGEL.Daniel
IGEL.Daniel Aug 27, 2015 at 10:30:48 (UTC)
Goto Top
Hallo ukulele,

das war schonmal super. Hab es soweit korrigiert, bekomme aber bei allen Werten außer C.name und MC.name ein "NULL" obwohl Werte drin sind

SELECT	C.name,
MC.name 'Hersteller',  
		DGC.designation 'Grafikkarte',  
		MDGC.name 'Hersteller',  
		DSC.designation 'Soundkarte',  
		MDSC.name 'Hersteller'  
FROM	glpi_computers C
LEFT JOIN glpi_manufacturers MC ON MC.id = C.manufacturers_id
LEFT JOIN glpi_devicegraphiccards DGC ON DGC.manufacturers_id = C.id
LEFT JOIN glpi_manufacturers MDGC ON MDGC.id = DGC.manufacturers_id
LEFT JOIN glpi_devicesoundcards DSC ON DSC.manufacturers_id = C.id
LEFT JOIN glpi_manufacturers MDSC ON MDSC.id = DGC.manufacturers_id
Member: ukulele-7
Solution ukulele-7 Aug 27, 2015 updated at 11:20:12 (UTC)
Goto Top
Deine Joins scheinen nicht sinnvoll. Der pk C.id wird nicht dem DGC.manufactures_id entsprechen, du joinst auf die falschen IDs. In der Haupttabelle glpi_computers muss es Fremdschlüssel geben die sagen welche Soundkarte, welche Grafikkarte, etc. verbaut ist. Oder du hast keine 1:n sondern eine n:m Beziehung, also noch eine Zwischentabelle.
SELECT	C.name,
		MC.name AS Hersteller,
		DGC.designation AS Grafikkarte,
		MDGC.name AS Hersteller,
		DSC.designation AS Soundkarte,
		MDSC.name AS Hersteller
FROM	glpi_computers C
-- Hersteller des Computers joinen
LEFT JOIN glpi_manufacturers MC ON C.manufacturers_id = MC.id
-- verbaute Grafikkarte joinen (Fremdschlüssel Grafikkarte = Primärschlüssel Grafikkarten-Tabelle)
LEFT JOIN glpi_devicegraphiccards DGC ON C.graphiccard_id = DGC.id
-- Hersteller der verbauten Grafikkarte joinen
LEFT JOIN glpi_manufacturers MDGC ON DGC.manufacturers_id = MDGC.id
--- das Selbe für Soundkarte
LEFT JOIN glpi_devicesoundcards DSC ON C.soundcard_id = DSC.id
LEFT JOIN glpi_manufacturers MDSC ON DSC.manufacturers_id = MDSC.id
-- weitere Komponenten
Member: IGEL.Daniel
IGEL.Daniel Aug 27, 2015 at 11:20:07 (UTC)
Goto Top
Nur zum Verständnis: ich kann die gleiche Tabelle x-mal joinen, ich muss ihr nur jedes Mal einen neuen Namen geben, richig?
Member: ukulele-7
Solution ukulele-7 Aug 27, 2015 updated at 12:23:19 (UTC)
Goto Top
Richtig und du musst zwischen den verschiedenen Joins wählen. In deinem Fall sollte LEFT JOIN aber eine gute Wahl sein.
Member: IGEL.Daniel
IGEL.Daniel Aug 27, 2015 at 14:30:56 (UTC)
Goto Top
Hallo ukulele,

habe mir Dank Deiner Hilfe jetzt in der Zwischenzeit eine ziemlich fiese aber funktionierende Query zusammengebastelt. Da ist mir noch ein Punkt aufgefallen: Es gibt Geräte mit zwei Netzwerkkarten und / oder zwei Soundkarten. Aktuell hätte ich 4 Einträge

| Gerät 1 | Netzwerkkarte 1 | Soundkarte 1 |
| Gerät 1 | Netzwerkkarte 1 | Soundkarte 2 |
| Gerät 1 | Netzwerkkarte 2 | Soundkarte 1 |
| Gerät 1 | Netzwerkkarte 2 | Soundkarte 2 |

Wie kann ich die jetzt so splitten, dass es in der Ausgabetabelle wie folgt ausschaut:

| Gerät 1 | Netzwerkkarte 1 | Netzwerkkarte 2 | Soundkarte 1 | Soundkarte 2 |

Danke
Member: ukulele-7
ukulele-7 Aug 27, 2015 at 14:56:37 (UTC)
Goto Top
Es gibt da viele Wege und auch einige recht komplizierte. Wenn es maximal zwei sind dann kannst du die zweite wie die erste Joinen. Hast du eine 1:n Beziehung zwischen glpi_computers und glpi_devicesoundcards oder eine n:m Beziehung? Wie sieht dein Query aus?
Member: IGEL.Daniel
IGEL.Daniel Aug 28, 2015 at 06:43:58 (UTC)
Goto Top
Guten Morgen Ukulele,

aber wie soll / muss ich denn joinen? Ich muss doch vohrer zählen, ob es doppelte Einträge in der Soundkarten / Netzwerkkarten Tabelle es mit der gleichen glpi_computers ID gibt...

Meine Query sieht aktuell wie folgt aus:

SELECT
	MF.name AS 'Hersteller', CM.name AS 'Modell', CT.name AS 'Typ', OS.name AS 'Betriebssystem'  
	, bios_version AS 'BIOS', BIOS.name AS 'Hersteller'  
	, CHIP.designation AS 'Prozessor', CHIP.name AS 'Hersteller', CHIP.frequence AS 'Taktfrequenz'  
	, RAM.designation AS 'Arbeitsspeicher', RAM.frequence AS 'Frequenz'  
	, GC.designation AS 'Grafikkarte', GC.name AS 'Hersteller'  
	, NC.designation AS 'Netzwerkkarte', NC.name AS 'Hersteller'  
	, SC.designation AS 'Soundkarte', SC.name AS 'Hersteller'  
FROM
	glpi_computers AS C
-- Herstellername
LEFT JOIN 
	glpi_manufacturers AS MF
ON
	C.manufacturers_id = MF.id
-- Modell
 LEFT JOIN
	glpi_computermodels AS CM
ON
	C.computermodels_id = CM.id
-- Typ
 LEFT JOIN
	glpi_computertypes AS CT
ON
	C.computertypes_id = CT.id
-- Operating System
LEFT JOIN
	glpi_operatingsystems AS OS
ON
	C.operatingsystems_id = OS.id
-- BIOS
LEFT JOIN
	(
SELECT
	M.name, bios_version, ICC.computers_id
FROM
	glpi_plugin_fusioninventory_inventorycomputercomputers AS ICC
LEFT JOIN
	glpi_manufacturers AS M
ON
	ICC.bios_manufacturers_id = M.id
	) BIOS
ON
	C.id = BIOS.computers_id
-- Prozessor
LEFT JOIN
	(
SELECT
	M.name, DP.designation, DP.frequence , IDP.items_id
FROM
	glpi_items_deviceprocessors AS IDP
LEFT JOIN
	glpi_deviceprocessors AS DP
ON
	IDP.deviceprocessors_id = DP.id
LEFT JOIN
	glpi_manufacturers AS M
ON
	DP.manufacturers_id = M.id
	) CHIP
ON
	C.id = CHIP.items_id
-- Arbeitsspeicher
LEFT JOIN
	(
SELECT
	DM.designation, DM.frequence, IDM.items_id
FROM
	glpi_items_devicememories AS IDM
LEFT JOIN
	glpi_devicememories AS DM
ON
	IDM.devicememories_id = DM.id
	) RAM
ON
	C.id = RAM.items_id
-- Grafikkarte
LEFT JOIN
	(
SELECT
	DGC.designation, M.name, IDGC.items_id
FROM
	glpi_items_devicegraphiccards AS IDGC
LEFT JOIN
	glpi_devicegraphiccards AS DGC
ON
	IDGC.devicegraphiccards_id = DGC.id
LEFT JOIN
	glpi_manufacturers AS M
ON
	DGC.manufacturers_id = M.id	
	) GC
ON
	C.id = GC.items_id
-- Netzwerkkarte
LEFT JOIN
	(
SELECT
	DNC.designation, M.name, IDNC.items_id
FROM
	glpi_items_devicenetworkcards AS IDNC
LEFT JOIN
	glpi_devicenetworkcards AS DNC
ON
	IDNC.devicenetworkcards_id = DNC.id
LEFT JOIN
	glpi_manufacturers AS M
ON
	DNC.manufacturers_id = M.id	
	) NC
ON
	C.id = NC.items_id
-- Soundkarte
LEFT JOIN
	(
SELECT
	DSC.designation, M.name, IDSC.items_id
FROM
	glpi_items_devicesoundcards AS IDSC
LEFT JOIN
	glpi_devicesoundcards AS DSC
ON
	IDSC.devicesoundcards_id = DSC.id
LEFT JOIN
	glpi_manufacturers AS M
ON
	DSC.manufacturers_id = M.id	
	) SC
ON
	C.id = SC.items_id

Gruß, Daniel
Member: ukulele-7
Solution ukulele-7 Aug 28, 2015 updated at 08:59:54 (UTC)
Goto Top
Bisher hast du nicht erwähnt ob es eine Zwischentabelle zu Soundkarten und Netzwerkkarten gibt, also eine n:m Beziehung, oder eine 1:n Beziehung ist. Da das Query schon echt lang ist würde ich das einmal Beispielhaft aufzeigen.

1:n Beziehung
SELECT	c.name AS Computer,
		s1.name AS Soundcard1,
		s2.name AS Soundcard2
FROM	computers c
LEFT JOIN (	SELECT	fk_computer,
					name
			FROM	soundcards
			ORDER BY pk
			LIMIT 1 ) s1
ON		c.pk = s1.fk_computer

LEFT JOIN (	SELECT	fk_computer,
					name
			FROM	soundcards
			ORDER BY pk
			LIMIT 1 OFFSET 1 ) s2
ON		c.pk = s2.fk_computer

n:m Beziehung
SELECT	c.name AS Computer,
		s1.name AS Soundcard1,
		s2.name AS Soundcard2
FROM	computers c
LEFT JOIN (	SELECT	fk_computer,
					fk_soundcard
			FROM	computers_soundcards
			ORDER BY pk
			LIMIT 1 ) z1
ON		c.pk = z1.fk_computer
LEFT JOIN soundcards s1
ON		z1.fk_soundcard = s1.pk
LEFT JOIN (	SELECT	fk_computer,
					fk_soundcard
			FROM	computers_soundcards
			ORDER BY pk
			LIMIT 1 OFFSET 1 ) z2
ON		c.pk = z2.fk_computer
LEFT JOIN soundcards s2
ON		z2.fk_soundcard = s2.pk

Durch ORDER BY und LIMIT kommt jetzt der erste Datensatz in der Zwischentabelle und wird als Verknüpfung für die erste Soundkarte genommen, das gleiche für die Zweite. Es könnte natürlich eine dritte Soundcard geben die jetzt nicht mehr angezeigt würde. Du siehst also die Lösung skaliert nicht besonders gut, in diesem Fall dürfte sie aber Sinn ergeben.

Alternativ gibt es bei MySQL glaube ich GROUP_CONCAT() und eventuell auch PIVOT. Ich bin aber nicht gut mit MySQL Syntax das müsstest du dir mal selber anschauen.
Member: IGEL.Daniel
IGEL.Daniel Aug 28, 2015 at 09:07:58 (UTC)
Goto Top
Hallo Ukulele,

hat wunderbar funktioniert. Vielen Dank! Und wegen der Skalierung - es gibt nicht mehr als zwei Sound- bzw. Netzwerkkarten.

Jetzt habe ich noch ein Frage - ich habe aktuell zwei Testdatensätze drin - also zwei Geräte mit jeweils zwei Sound- und Netzwerkkarten. Wenn ich die komplette Query laufen lasse, werden bei Gerät 1 alle Karten angezeigt, bei Gerät 2 aber nicht. Hab es mal mit einem WHERE probiert - bei Gerät 1 werden wieder alle Karten angezeigt. Beim WHERE auf Gerät 2 fehlen wieder die Karten. Alle anderen Infos sind da. Nehme ich die alte Abfrage von gestern, wo alle Karten untereinander stehen, werden alle Karten angezeigt. Hängt das irgendwie mit dem ORDER BY und LIMIT zusammen?

Danke, Daniel
Member: ukulele-7
ukulele-7 Aug 28, 2015 at 09:18:13 (UTC)
Goto Top
Möglich, vermutlich hast du einen kleinen Fehler eingebaut.

ORDER BY = Nach was du sortierst ist eigentlich egal, wichtig ist das eine Sortierung definiert wird sonst ist die DB nicht "gezwungen" die Daten jedes mal gleich zu sortieren.
LIMIT = begrenzt die Anzahl der Datensätze auf 1, wählt also den ersten.
LIMIT mit OFFSET = begrenzt auch die Anzahl auf 1, verwirft aber den ersten und nimmt dann den zweiten.

Hast du vieleicht OFFSET vergessen? Ansonsten musst du nochmal den Code posten.
Member: IGEL.Daniel
IGEL.Daniel Aug 28, 2015 at 09:23:56 (UTC)
Goto Top
Hallo Ukulele,

folgend der Codeschnipsel:

SELECT
	C.id
	, NC1.designation AS 'Netzwerkkarte 1', NC1.name AS 'Hersteller'  
	, NC2.designation AS 'Netzwerkkarte 2', NC2.name AS 'Hersteller'  
	, SC1.designation AS 'Soundkarte 1', SC1.name AS 'Hersteller'  
	, SC2.designation AS 'Soundkarte 2', SC1.name AS 'Hersteller'  
FROM
	glpi_computers AS C
-- Netzwerkkarten
LEFT JOIN
	(
	SELECT
		DNC.designation, M.name, IDNC.items_id, IDNC.id
	FROM
		glpi_items_devicenetworkcards AS IDNC
	LEFT JOIN
		glpi_devicenetworkcards AS DNC
	ON
		IDNC.devicenetworkcards_id = DNC.id
	LEFT JOIN
		glpi_manufacturers AS M
	ON
		DNC.manufacturers_id = M.id
	ORDER BY
		IDNC.id
	LIMIT 1
	) NC1
ON
	C.id = NC1.items_id
LEFT JOIN
	(
	SELECT
		DNC.designation, M.name, IDNC.items_id, IDNC.id
	FROM
		glpi_items_devicenetworkcards AS IDNC
	LEFT JOIN
		glpi_devicenetworkcards AS DNC
	ON
		IDNC.devicenetworkcards_id = DNC.id
	LEFT JOIN
		glpi_manufacturers AS M
	ON
		DNC.manufacturers_id = M.id
	ORDER BY
		IDNC.id
	LIMIT 1 OFFSET 1
	) NC2
ON
	C.id = NC2.items_id
-- Soundkarten
LEFT JOIN
	(
	SELECT
		DSC.designation, M.name, IDSC.items_id, IDSC.id
	FROM
		glpi_items_devicesoundcards AS IDSC
	LEFT JOIN
		glpi_devicesoundcards AS DSC
	ON
		IDSC.devicesoundcards_id = DSC.id
	LEFT JOIN
		glpi_manufacturers AS M
	ON
		DSC.manufacturers_id = M.id
	ORDER BY
		IDSC.id
	LIMIT 1
	) SC1
ON
	C.id = SC1.items_id
LEFT JOIN
	(
	SELECT
		DSC.designation, M.name, IDSC.items_id, IDSC.id
	FROM
		glpi_items_devicesoundcards AS IDSC
	LEFT JOIN
		glpi_devicesoundcards AS DSC
	ON
		IDSC.devicesoundcards_id = DSC.id
	LEFT JOIN
		glpi_manufacturers AS M
	ON
		DSC.manufacturers_id = M.id
	ORDER BY
		IDSC.id
	LIMIT 1 OFFSET 1
	) SC2
ON
	C.id = SC2.items_id
Member: ukulele-7
ukulele-7 Aug 28, 2015 at 10:09:34 (UTC)
Goto Top
Zeile 6
, SC2.designation AS 'Soundkarte 2', SC1.name AS 'Hersteller'
muss wohl
, SC2.designation AS 'Soundkarte 2', SC2.name AS 'Hersteller'
sein

Was anderes fällt mir spontan nicht auf.
Member: IGEL.Daniel
IGEL.Daniel Aug 28, 2015 at 11:15:36 (UTC)
Goto Top
Hallo Ukulele,

Danke für den Hinweis, ich habe den Fahler korrigiert. Daran liegt es aber leider nicht. Muss ich weitersuchen / fragen.

Nichtsdestotrotz noch einmal vielen Dank für Deine Hilfe, ohne die ich eh nicht so weit gekommen wäre.

Beste Grüße,
Daniel
Member: ukulele-7
ukulele-7 Aug 28, 2015 at 11:51:03 (UTC)
Goto Top
Wenn es nur 2 Computer und 4 Karten sind poste doch mal diese Datensätze und dein Ergebniss, der Fehler muss dann eigentlich in den Daten liegen.
Member: IGEL.Daniel
IGEL.Daniel Aug 28, 2015 updated at 12:15:09 (UTC)
Goto Top
Hallo ukulele,

es hängt anscheinend mit der eindeutigen ID des jeweiligen Geräts zusammen. Ich habe nämlich das Grät mit der kleineren ID rausgeschmissen und dafür ein neues Gerät importiert.

Resultat: Bei dem Gerät, das vorher die größere ID hatte, jetzt aber die kleinere, werden jetzt alle Karten angezeigt. Bei dem neu importierten Gerät werden keine Karten angezeigt.

Dafür taucht das neue Gerät 2x in der Ergebnis-Tabelle auf.

Gruß
Member: ukulele-7
ukulele-7 Aug 28, 2015 at 12:33:53 (UTC)
Goto Top
Oh ja das habe ich nicht bedacht. Bei MSSQL würde ich mit ROW_NUMBER und PARTION BY arbeiten und etwas anders vorgehen, das gibt es bei MySQL aber nicht. LIMIT reicht hier nicht aus.

Folgendes passiert: Du Joinst die Netzwerkkartentabelle aus einem Subquery das die Anzahl der Zeilen auf 1 reduziert. Allerdings gibt es keine Einschränkungen bei der Auswahl so das der verbleibende Datensatz nicht zwigend zu dem Hauptdatensatz (dem Cumputer) passt. Ergo kriegst du maximal einmal eine richtige Zuordnung.

Du kannst jetzt entweder mit WHERE weiter einschränken:
LEFT JOIN
	(
	SELECT
		DNC.designation, M.name, IDNC.items_id, IDNC.id
	FROM
		glpi_items_devicenetworkcards AS IDNC
	LEFT JOIN
		glpi_devicenetworkcards AS DNC
	ON
		IDNC.devicenetworkcards_id = DNC.id
	LEFT JOIN
		glpi_manufacturers AS M
	ON
		DNC.manufacturers_id = M.id
WHERE  IDNC.items_id = C.id
	ORDER BY
		IDNC.id
	LIMIT 1
	) NC1
ON
	C.id = NC1.items_id
Damit machst du im Subselect einen abgleich mit einer Spalte außerhalb des Subselects. Diese Bedingung ist also defakto doppelt, du könntest also auch deinen ganzen Subselect (mit dem WHERE und ohne LEFT JOIN und ON) in die Spaltenliste schreiben.

Es ginge auch eleganter aber wie schon erwähnt, MySQL ist nicht so mein Alltag.
Member: IGEL.Daniel
IGEL.Daniel Aug 28, 2015 at 13:05:09 (UTC)
Goto Top
Hallo ukulele,

wenn ich das WHERE verwende, kommt die Fehlermeldung, dass die Spalte "C.id" in der WHERE Anweisung nicht bekannt ist...

Gruß, Daniel
Member: ukulele-7
ukulele-7 Aug 28, 2015 at 13:33:16 (UTC)
Goto Top
Hm noch son Ding was in MySQL nicht geht...

Das Beste wird sein du baust dir für die Tabellen glpi_items_devicenetworkcards und glpi_items_devicesoundcards jeweils eine Sicht in der du ROW_NUMBER und PARTION BY "simulierst". Das wäre in etwa so:
CREATE VIEW view_glpi_items_devicenetworkcards
SELECT	@row_number := (	CASE
							WHEN	@db_names = db_names
							THEN	@row_number + 1
							ELSE	1
							END ) AS row_number,
		@db_names := items_id AS db_names
		items_id,
		devicenetworkcards_id
FROM	glpi_items_devicenetworkcards,
		(	SELECT	@row_number := 0,
					@db_names := '') AS t  
Quelle: http://blog.sqlauthority.com/2014/03/09/mysql-reset-row-number-for-each ...
Ich kann das leider nicht testen.
Damit joinst du dann etwa so:
SELECT	C.id,
		NC1.designation AS 'Netzwerkkarte 1',  
		NC1m.name AS 'Hersteller',  
		NC2.designation AS 'Netzwerkkarte 2',  
		NC2m.name AS 'Hersteller'  
FROM	glpi_computers AS C
-- Netzwerkkarten
LEFT JOIN view_glpi_items_devicenetworkcards NC1z
ON		C.id = NC1z.items_id
AND		NC1z.row_number = 1
LEFT JOIN glpi_devicenetworkcards NC1
ON		NC1z.devicenetworkcards_id = NC1.id
LEFT JOIN glpi_manufacturers NC1m
ON		NC1.manufacturers_id = NC1m.id
LEFT JOIN view_glpi_items_devicenetworkcards NC2z
ON		C.id = NC2z.items_id
AND		NC2z.row_number = 2
LEFT JOIN glpi_devicenetworkcards NC2
ON		NC2z.devicenetworkcards_id = NC2.id
LEFT JOIN glpi_manufacturers NC2m
ON		NC2.manufacturers_id = NC2m.id
Member: IGEL.Daniel
IGEL.Daniel Aug 28, 2015 at 15:00:26 (UTC)
Goto Top
Hallo ukulele,

nur zum Verständnis... hier soll (weil es geht nicht) bei jeder Abfrage jeweils die View für jedes Gerät mit den beiden Grafikkarten bzw. Netzwerkkarten befüllt, richtig?

Gruß und schönes Wochenende,
Daniel
Member: ukulele-7
ukulele-7 Aug 31, 2015 at 07:30:51 (UTC)
Goto Top
Nein nicht ganz. Die View soll der Tabelle glpi_items_devicenetworkcards nur eine Zeilennummer hinzufügen die die Netzwerkkarten pro Computer durchzählt und dann wieder auf Null springt. Normalerweise würde ich das mit
ROW_NUMBER() OVER (ORDER BY devicenetworkcards_id PARTITION BY items_id)
machen. Diese Zeilennummer kann ich dann im Join als Kriterium verwenden.
Member: IGEL.Daniel
IGEL.Daniel Sep 08, 2015 at 11:50:10 (UTC)
Goto Top
Hallo ukulele,

habe noch einen anderen Experten gefragt. Er hat das Problem mittels ON Bedingung und GROUP BY gelöst:

SELECT
	  C.name, MF.name AS 'Hersteller', CM.name AS 'Modell', CT.name AS 'Typ', OS.name AS 'Betriebssystem'  
	, bios_version AS 'BIOS', BIOS.name AS 'Hersteller'  
	, CHIP.designation AS 'Prozessor', CHIP.name AS 'Hersteller', CHIP.frequence AS 'Taktfrequenz'  
	, RAM.designation AS 'Arbeitsspeicher', RAM.frequence AS 'Frequenz'  
	, GC.designation AS 'Grafikkarte', GC.name AS 'Hersteller'  
	, NC1.designation AS 'Netzwerkkarte 1', NC1.name AS 'Hersteller'  
	, NC2.designation AS 'Netzwerkkarte 2', NC2.name AS 'Hersteller'  
	, SC1.designation AS 'Soundkarte 1', SC1.name AS 'Hersteller'  
	, SC2.designation AS 'Soundkarte 2', SC2.name AS 'Hersteller'  
FROM
	glpi_computers AS C
-- Herstellername
LEFT JOIN glpi_manufacturers AS MF ON C.manufacturers_id = MF.id
-- Modell
LEFT JOIN glpi_computermodels AS CM ON C.computermodels_id = CM.id
-- Typ
LEFT JOIN glpi_computertypes AS CT ON C.computertypes_id = CT.id
-- Operating System
LEFT JOIN glpi_operatingsystems AS OS ON C.operatingsystems_id = OS.id
-- BIOS
LEFT JOIN
	(
		SELECT	M.name, bios_version, ICC.computers_id
		FROM      glpi_plugin_fusioninventory_inventorycomputercomputers AS ICC
		LEFT JOIN glpi_manufacturers AS M ON ICC.bios_manufacturers_id = M.id
	) BIOS ON C.id = BIOS.computers_id
-- Prozessor
LEFT JOIN
	(
		SELECT	M.name, DP.designation, DP.frequence , IDP.items_id
		FROM	glpi_items_deviceprocessors AS IDP
		LEFT JOIN glpi_deviceprocessors AS DP ON IDP.deviceprocessors_id = DP.id
		LEFT JOIN glpi_manufacturers AS M ON DP.manufacturers_id = M.id
	) CHIP ON C.id = CHIP.items_id
-- Arbeitsspeicher
LEFT JOIN
	(
		SELECT DM.designation, DM.frequence, IDM.items_id
		FROM glpi_items_devicememories AS IDM
		LEFT JOIN glpi_devicememories AS DM ON IDM.devicememories_id = DM.id
	) RAM ON C.id = RAM.items_id
-- Grafikkarte
LEFT JOIN
	(
		SELECT DGC.designation, M.name, IDGC.items_id
		FROM glpi_items_devicegraphiccards AS IDGC
		LEFT JOIN glpi_devicegraphiccards AS DGC ON IDGC.devicegraphiccards_id = DGC.id
		LEFT JOIN glpi_manufacturers AS M ON DGC.manufacturers_id = M.id	
	) GC ON C.id = GC.items_id
-- Netzwerkkarten
LEFT JOIN
	(
		SELECT DNC.designation, M.name, IDNC.items_id, IDNC.id, IDNC.devicenetworkcards_id
		FROM  glpi_items_devicenetworkcards AS IDNC
	LEFT JOIN glpi_devicenetworkcards AS DNC ON IDNC.devicenetworkcards_id = DNC.id
	LEFT JOIN glpi_manufacturers AS M ON DNC.manufacturers_id = M.id
	) NC1 ON C.id = NC1.items_id 
LEFT JOIN
	(
		SELECT DNC.designation, M.name, IDNC.items_id, IDNC.id, IDNC.devicenetworkcards_id
		FROM glpi_items_devicenetworkcards AS IDNC
		LEFT JOIN glpi_devicenetworkcards AS DNC ON IDNC.devicenetworkcards_id = DNC.id
		LEFT JOIN glpi_manufacturers AS M ON
		DNC.manufacturers_id = M.id
	) NC2 ON C.id = NC2.items_id and NC2.devicenetworkcards_id != NC1.devicenetworkcards_id
-- Soundkarten
LEFT JOIN
	(
		SELECT DSC.designation, M.name, IDSC.items_id, IDSC.id, IDSC.devicesoundcards_id
		FROM glpi_items_devicesoundcards AS IDSC
		LEFT JOIN glpi_devicesoundcards AS DSC ON IDSC.devicesoundcards_id = DSC.id
		LEFT JOIN glpi_manufacturers AS M ON DSC.manufacturers_id = M.id
	) SC1 ON C.id = SC1.items_id
LEFT JOIN
	(
		SELECT DSC.designation, M.name, IDSC.items_id, IDSC.id,IDSC.devicesoundcards_id
		FROM glpi_items_devicesoundcards AS IDSC
		LEFT JOIN glpi_devicesoundcards AS DSC ON IDSC.devicesoundcards_id = DSC.id
		LEFT JOIN glpi_manufacturers AS M ON DSC.manufacturers_id = M.id
	) SC2 ON C.id = SC2.items_id and SC2.devicesoundcards_id !=SC1.devicesoundcards_id
GROUP BY C.id
Member: ukulele-7
ukulele-7 Sep 08, 2015 at 14:42:00 (UTC)
Goto Top
Joa das müsste gehen.
Member: Biber
Biber Sep 08, 2015 at 16:53:51 (UTC)
Goto Top
Moin IGEL.Daniel,

mal rein interessehalber....
Was wäre denn der signifikante Unterschied, wenn du die letzte Zeile "GROUP BY C.id" ersatzlos streichst?

Ich sehe keine Aggregat-Funktionen und auch keinen Bedarf dafür.
Frisst IMHO doch nur sinnlos Resourcen ... dann doch lieber die Kohle spenden statt zu verbrennen.

Spendenkonto-Nummern kann ich bei Bedarf nachreichen. face-wink

Grüße
Biber
Member: ukulele-7
ukulele-7 Sep 09, 2015 at 06:38:53 (UTC)
Goto Top
Stimmt auf das GROUP BY habe ich gar nicht geachtet. Ist nicht nur Ressourcenfressend sondern auch syntaktisch falsch. Bei einer guten relationalen Datenbank würde ein Fehler kommen, bei MySQL soll das glaube ich auch bald gefixt werden.
Member: IGEL.Daniel
IGEL.Daniel Sep 09, 2015 at 07:00:36 (UTC)
Goto Top
Servus Biber,

dann werden mir - bei z.B. jeweils 2 Sound- und Netzwerkkarten - vier identische Datensätze angezeigt

Gruß,
Daniel
Member: Biber
Biber Sep 09, 2015 at 07:48:46 (UTC)
Goto Top
Moin IGEL.Daniel und ukulele-7,


da muss ich jezz' mal bei einem Frühstückskäffchen drüber nachdenken, wieso das passiert....

Nichtsdestotrotz - wenn mehrere identische Sätze eingedampft werden sollen, dann wäre das probate Mittel

SELECT DISTINCT
	  C.name, MF.name AS 'Hersteller', CM.name AS 'Modell',   
  --- <und der Rest der obigen Query...
 --  aber ohne GROUP BY>

Wie ukulele-7 schon schrieb -eigentlich sollte eine Syntax-Fehlermeldung kommen und kein Resultset.

Ich hol erstma' Kaffee.

Grüße
Biber
Member: IGEL.Daniel
IGEL.Daniel Sep 09, 2015 at 07:57:56 (UTC)
Goto Top
Servus,

ich muss die Query nicht auf Teufel komm raus optimieren, da die Abfrage in sporadischen Abständen händisch ausgeführt und exportiert wird. Die dabei generierten Datensätze sind zudem ziemlich klein.

Beste Grüße,
Daniel
Member: ukulele-7
ukulele-7 Sep 09, 2015 at 15:07:51 (UTC)
Goto Top
Dann solltest du wirklich mit DISTINCT arbeiten und nicht mit GROUP BY, falls dieses Verhalten bei MySQL geändert wird.
http://dev.mysql.com/doc/refman/5.0/en/group-by-handling.html
Member: IGEL.Daniel
IGEL.Daniel Sep 10, 2015 at 08:02:42 (UTC)
Goto Top
Hallo ukulele, Hallo Biber,

ich hab es ausprobiert. Wenn ich DISTINCT statt GROUP BY nehme, werden mir wieder - bei z.B. jeweils 2 Sound- und Netzwerkkarten - vier identische Datensätze angezeigt. Also das gleiche Resultat wenn ich nur das GROUP BY raussschmeiße.

Gruß, Daniel